Unterschied zwischen langsamen und schnellen Systemaufrufen


13

Was ist der Unterschied zwischen langsamen und schnellen Systemaufrufen? Ich habe gelernt, dass langsame Systemaufrufe blockieren können, wenn der Prozess einige Signale empfängt, weil die abgefangenen Signale den blockierten Systemaufruf möglicherweise aufwecken, aber ich kann diesen Mechanismus nicht genau verstehen. Irgendwelche Beispiele wären willkommen.

Antworten:


19

Tatsächlich gibt es drei Abstufungen bei Systemaufrufen.

  1. Einige Systemaufrufe kehren sofort zurück. "Sofort" bedeutet, dass sie nur ein wenig Prozessorzeit benötigen. Es gibt keine feste Grenze, wie lange sie dauern können (außer in Echtzeitsystemen ), aber diese Anrufe kehren zurück, sobald sie lange genug geplant wurden.
    Diese Anrufe werden normalerweise als nicht blockierend bezeichnet . Beispiele für nicht-blockierende Anrufe sind Anrufe , die nur ein bisschen Systemzustand lesen, oder eine einfache Änderung des Systemstatus machen, wie getpid, gettimeofday, getuidoder setuid. Einige Systemaufrufe können je nach den Umständen blockierend oder nicht blockierend sein. readBlockiert beispielsweise niemals, wenn die Datei eine Pipe oder ein anderer Typ ist, der nicht blockierende Lesevorgänge unterstützt und das O_NONBLOCKFlag gesetzt ist.
  2. Es kann eine Weile dauern, bis einige Systemaufrufe abgeschlossen sind, aber nicht für immer. Ein typisches Beispiel ist sleep.
  3. Einige Systemaufrufe werden erst zurückgegeben, wenn ein externes Ereignis eintritt. Diese Anrufe sollen blockieren . Beispielsweise readblockiert ein aufgerufener Dateideskriptor, und das ist es auch wait.

Die Unterscheidung zwischen "schnellen" und "langsamen" Systemaufrufen ist aus Sicht des Kernel-Implementierers nahezu nicht blockierend oder blockierend. Es ist bekannt, dass ein schneller Systemaufruf ausgeführt werden kann, ohne zu blockieren oder zu warten. Wenn der Kernel auf einen schnellen Systemaufruf stößt, weiß er, dass er den Systemaufruf sofort ausführen und den gleichen Vorgang einplanen kann. (In einigen Betriebssystemen mit nicht präemptivem Multitasking sind schnelle Systemaufrufe möglicherweise nicht präemptiv. Dies ist in normalen Unix-Systemen nicht der Fall.) Auf der anderen Seite muss bei einem langsamen Systemaufruf möglicherweise gewartet werden, bis eine andere Aufgabe abgeschlossen ist, also der Kernel muss sich darauf vorbereiten, den aufrufenden Prozess anzuhalten und eine andere Task auszuführen.

In einigen Fällen handelt es sich um eine Grauzone. Beispielsweise wird ein Festplattenlesevorgang ( readaus einer regulären Datei) normalerweise als nicht blockierend angesehen, da er nicht auf einen anderen Prozess wartet. Es muss nur auf die Festplatte gewartet werden. Die Beantwortung dauert normalerweise nur ein wenig, dauert jedoch nicht ewig (so wie in Fall 2 oben). Aus Sicht des Kernels muss der Prozess jedoch warten, bis der Festplattentreiber vollständig ist, sodass es sich definitiv um einen langsamen Systemaufruf handelt.


danke schön! Aber wenn die Datei eine Pipe ist, ist das Lesen der Datei nicht blockierend? siehe www2.hawaii.edu/~esb/2007spring.ics612/apr10.html
KayKay

es bedeutet "langsames Lesen / Schreiben (z. B. auf einer Pipe oder einem Terminal)"
KayKay

@KayKay: Für eine Pipe können Sie je nach Status der O_NONBLOCKFlagge beides haben . Wenn das Flag gesetzt ist, kann der Systemaufruf abgeschlossen werden, ohne auf etwas anderes zu warten, sodass er nicht blockiert, und der Kernel kann ihn als schnellen Systemaufruf behandeln.
Gilles 'SO- hör auf böse zu sein'

Du meinst, es hängt von der O_NONBLOCK-Flagge ab!
KayKay

3

Ein langsamer Systemaufruf ist so etwas wie ein TCP-Socket read () - wenn Sie O_ASYNC (oder was auch immer) nicht gesetzt haben, kann er ewig warten.

Ein schneller Systemaufruf ist so etwas wie gettimeofday () oder getpid (), die beide Informationen an den Prozess zurückgeben, den der Kernel sofort verfügbar hat.

Datenträgerlesevorgänge fallen in die Kategorie langsamer Systemaufrufe. Wenn ein Prozess read () für eine echte Festplattendatei oder einen Dateideskriptor ausführt, muss der Kernel möglicherweise einen oder mehrere Plattenblöcke einlesen, um den Lesevorgang durchzuführen. Abhängig von der On-Disk-Struktur des zugrunde liegenden Dateisystems kann dies bedeuten, den On-Disk-Inode zu lesen, um die Plattenblocknummer eines "indirekten Blocks" zu erhalten, den indirekten Block zu lesen, um den Datenblock zu erhalten, und dann den Datenblock selbst zu lesen . Ziemlich zeitaufwendig, zumindest in Bezug auf die CPU-Zyklen pro Plattenzugriff, wahrscheinlich heute schlechter als in der guten alten Zeit.

Ich habe das schon seit Ewigkeiten nicht mehr gesehen, aber die "untere Hälfte" des alten Unix-Laufwerk-Gerätetreibercodes blockierte Signale / Interrupts, so dass die Integrität des Dateisystems auf der Festplatte einfacher aufrecht erhalten werden konnte. Gelegentlich lieferte ein fehlerhafter Treiber oder eine fehlerhafte Festplatte niemals den Festplattenblock, den ein Prozess angefordert hatte, und der Prozess schlief für immer. Sogar ein Kill -9 hat nichts getan.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.