Linux-Prozesszustände


89

Was passiert unter Linux mit dem Status eines Prozesses, wenn er Blöcke von einer Festplatte lesen muss? Ist es blockiert? Wenn ja, wie wird ein anderer Prozess zur Ausführung ausgewählt?

Antworten:


86

Während des Wartens auf read()oder write()von / zu einer Dateideskriptor-Rückgabe wird der Prozess in eine spezielle Art von Ruhezustand versetzt, die als "D" oder "Disk Sleep" bezeichnet wird. Dies ist etwas Besonderes, da der Prozess in einem solchen Zustand nicht abgebrochen oder unterbrochen werden kann. Ein Prozess, der auf eine Rückkehr von ioctl () wartet, wird ebenfalls auf diese Weise in den Ruhezustand versetzt.

Eine Ausnahme ist, wenn eine Datei (z. B. ein Terminal oder ein anderes Zeichengerät) im O_NONBLOCKModus geöffnet wird und übergeben wird, wenn angenommen wird, dass ein Gerät (z. B. ein Modem) Zeit zum Initialisieren benötigt. Sie haben jedoch in Ihrer Frage Blockgeräte angegeben. Außerdem habe ich noch nie einen versucht ioctl(), der wahrscheinlich auf einem im nicht blockierenden Modus geöffneten fd blockiert (zumindest nicht wissentlich).

Wie ein anderer Prozess ausgewählt wird, hängt ganz vom verwendeten Scheduler ab sowie davon, was andere Prozesse möglicherweise getan haben, um ihre Gewichtung in diesem Scheduler zu ändern.

Es ist bekannt, dass einige User Space-Programme unter bestimmten Umständen für immer in diesem Zustand bleiben, bis sie neu gestartet werden. Diese werden normalerweise mit anderen "Zombies" gruppiert, aber der Begriff wäre nicht korrekt, da sie technisch nicht verstorben sind.


1
"Ein Prozess, der auf eine Rückkehr von ioctl () wartet, würde auf diese Weise ebenfalls in den Ruhezustand versetzt." Ich habe gerade meinen Userspace-Prozess beendet und auf eine blockierende IOCTL gewartet, daher ist dies nicht der Fall. Es sei denn, ich missverstehe
Hamzahfrq

Es wäre enorm schwierig, einen solchen Test zeitlich festzulegen. Unterbrechungsfreie Prozesse können nicht beendet werden. Wenn Sie es töten konnten, wurde es einfach blockiert (der Kernel befand sich nicht in der Mitte eines Teils des ioctl und kopierte die entsprechende Antwort auf den Benutzerbereich an der Stelle, an der Sie vorbeigegangen sind (oder zumindest nicht in der mitten im Kopieren)). Linux hat sich auch verändert viel seit 2009 , als dies geschrieben wurde; Das Phänomen ist viel weniger beobachtbar als früher.
Tim Post

133

Wenn ein Prozess Daten von einer Festplatte abrufen muss, wird die Ausführung auf der CPU effektiv gestoppt, damit andere Prozesse ausgeführt werden können, da der Vorgang möglicherweise lange dauert. Mindestens 5 ms Suchzeit für eine Festplatte sind üblich, und 5 ms sind 10 Millionen CPU-Zyklen, eine Ewigkeit aus Sicht des Programms!

Aus Sicht des Programmierers (auch "im Benutzerbereich" genannt) wird dies als blockierender Systemaufruf bezeichnet . Wenn Sie aufrufen write(2)(dies ist ein dünner libc-Wrapper um den gleichnamigen Systemaufruf), stoppt Ihr Prozess nicht genau an dieser Grenze. Im Kernel wird der Systemaufrufcode fortgesetzt. Meistens geht es bis zu einem bestimmten Festplattencontrollertreiber (Dateiname → Dateisystem / VFS → Blockgerät → Gerätetreiber), bei dem ein Befehl zum Abrufen eines Blocks auf der Festplatte an die richtige Hardware gesendet wird die meiste Zeit schneller Betrieb.

DANN wird der Prozess in den Ruhezustand versetzt (im Kernelraum wird das Blockieren als "Schlafen" bezeichnet - aus der Sicht des Kernels wird nie etwas "blockiert"). Es wird aktiviert, sobald die Hardware die richtigen Daten abgerufen hat. Der Prozess wird dann als ausführbar markiert und geplant. Schließlich führt der Scheduler den Prozess aus.

Schließlich wird im Benutzerbereich der blockierende Systemaufruf mit dem richtigen Status und den richtigen Daten zurückgegeben, und der Programmablauf wird fortgesetzt.

Es ist möglich, die meisten E / A-Systemaufrufe im nicht blockierenden Modus aufzurufen (siehe O_NONBLOCKin open(2)und fcntl(2)). In diesem Fall kehren die Systemaufrufe sofort zurück und melden nur das Senden der Festplattenoperation. Der Programmierer muss zu einem späteren Zeitpunkt explizit prüfen, ob der Vorgang erfolgreich abgeschlossen wurde oder nicht, und sein Ergebnis abrufen (z select(2). B. mit ). Dies wird als asynchrone oder ereignisbasierte Programmierung bezeichnet.

Die meisten Antworten, die hier den D-Status erwähnen (der TASK_UNINTERRUPTIBLEin den Linux-Statusnamen genannt wird), sind falsch. Der D- Zustand ist ein spezieller Schlafmodus, der nur in einem Kernel-Space-Code-Pfad ausgelöst wird, wenn dieser Code-Pfad nicht unterbrochen werden kann (weil er zu komplex zum Programmieren wäre), mit der Erwartung, dass er nur für einen sehr blocken würde kurze Zeit. Ich glaube, dass die meisten "D-Zustände" tatsächlich unsichtbar sind; Sie sind sehr kurzlebig und können mit Stichprobenwerkzeugen wie „top“ nicht beobachtet werden.

In einigen Situationen können im D-Zustand nicht abtötbare Prozesse auftreten. NFS ist dafür berühmt und ich habe es schon oft erlebt. Ich denke, es gibt einen semantischen Konflikt zwischen einigen VFS-Codepfaden, die davon ausgehen, dass immer lokale Festplatten erreicht werden und eine schnelle Fehlererkennung (bei SATA würde ein Fehlerzeitlimit bei einigen 100 ms liegen) und NFS, das tatsächlich Daten aus dem Netzwerk abruft ist widerstandsfähiger und hat eine langsame Wiederherstellung (ein TCP-Timeout von 300 Sekunden ist üblich). Lesen Sie diesen Artikel für die coole Lösung, die in Linux 2.6.25 mit dem TASK_KILLABLEStatus eingeführt wurde. Vor dieser Ära gab es einen Hack, bei dem Sie tatsächlich Signale an NFS-Prozessclients senden konnten, indem Sie ein SIGKILL an den Kernel-Thread senden rpciod, aber vergessen Sie diesen hässlichen Trick.…


2
+1 für die detaillierte Antwort, aber bitte beachten Sie, dass dieser Thread seit fast zwei Jahren eine akzeptierte Antwort hat. Klicken Sie auf den Link "Fragen", wenn Sie neuere Fragen beantworten möchten. Willkommen bei Stack Overflow und vielen Dank für Ihren Beitrag!
GargantuChet

20
Diese Antwort ist die einzige, die NFS erwähnt, was in einigen Umgebungen die häufigste Erklärung für Prozesse im D-Zustand ist. +1.
Pinko

14
Sehr gute Antwort, danke. Beachten Sie auch, dass der Prozess in den D-Status versetzt wird, während auf ausgelagerte Seiten gewartet wird, sodass sich ein Thrashing-Prozess für eine lange Zeit im D-Status befindet.
Cha0site

@zerodeux gute Antwort, aber ich denke, Ihr Schema (Dateiname -> Dateisystem / VFS -> Gerät blockieren -> Gerätetreiber) sollte es sein (Dateiname -> VFS -> Dateisystem (ext3) -> Gerät blockieren -> Gerätetreiber)
c4f4t0r

1
Wäre es sicher anzunehmen, dass die im Kernel verbrachte Zeit, die auf Spinlocks wartet (die möglicherweise mit der Festplatten-E / A zusammenhängen oder nicht), alle als D-Status in gemeldet wird /proc/stat?
Docht

8

Ein Prozess, der E / A ausführt, wird in den D-Zustand versetzt (unterbrechungsfreier Ruhezustand) , wodurch die CPU freigegeben wird, bis ein Hardware-Interrupt auftritt , der die CPU anweist, zur Ausführung des Programms zurückzukehren. Siehe man psfür die anderen Prozesszustände.

Abhängig von Ihrem Kernel gibt es einen Prozessplaner , der eine Runqueue von Prozessen verfolgt, die zur Ausführung bereit sind. Zusammen mit einem Planungsalgorithmus teilt es dem Kernel mit, welcher Prozess welcher CPU zugewiesen werden soll. Es sind Kernelprozesse und Benutzerprozesse zu berücksichtigen. Jedem Prozess wird eine Zeitscheibe zugewiesen, die einen Teil der CPU-Zeit darstellt, die er verwenden darf. Sobald der Prozess seine gesamte Zeitscheibe verwendet hat, wird er als abgelaufen markiert und erhält im Planungsalgorithmus eine niedrigere Priorität.

Im 2.6-Kernel gibt es einen O (1) -Zeitkomplexitätsplaner. Unabhängig davon , wie viele Prozesse ausgeführt werden, werden CPUs in konstanter Zeit zugewiesen. Es ist jedoch komplizierter, da in Version 2.6 Preemption eingeführt wurde und der CPU-Lastausgleich kein einfacher Algorithmus ist. In jedem Fall ist es effizient und die CPUs bleiben nicht im Leerlauf, während Sie auf die E / A warten.


3

Wie bereits von anderen erklärt, sind Prozesse im "D" -Zustand (unterbrechungsfreier Schlaf) für das Aufhängen des ps-Prozesses verantwortlich. Mir ist das schon oft mit RedHat 6.x und automatisch bereitgestellten NFS-Home-Verzeichnissen passiert.

Um Prozesse im Status D aufzulisten, können Sie die folgenden Befehle verwenden:

cd /proc
for i in [0-9]*;do echo -n "$i :";cat $i/status |grep ^State;done|grep D

Um das aktuelle Verzeichnis des Prozesses und möglicherweise die gemountete NFS-Festplatte mit Problemen zu kennen, können Sie einen Befehl verwenden, der dem folgenden Beispiel ähnelt (ersetzen Sie 31134 durch die Nummer des Ruhezustands):

# ls -l /proc/31134/cwd
lrwxrwxrwx 1 pippo users 0 Aug  2 16:25 /proc/31134/cwd -> /auto/pippo

Ich fand heraus, dass das Geben des Befehls umount mit dem Schalter -f (force) an das zugehörige gemountete nfs-Dateisystem den Schlafprozess aufwecken konnte:

umount -f /auto/pippo

Das Dateisystem wurde nicht ausgehängt, da es ausgelastet war, aber der zugehörige Prozess wurde aktiviert und ich konnte das Problem ohne Neustart lösen.


1

Angenommen, Ihr Prozess ist ein einzelner Thread und Sie verwenden blockierende E / A., blockiert Ihr Prozess das Warten auf den Abschluss der E / A. Der Kernel wählt einen anderen Prozess aus, der in der Zwischenzeit ausgeführt werden soll, basierend auf der Genauigkeit, Priorität, der letzten Laufzeit usw. Wenn keine anderen ausführbaren Prozesse vorhanden sind, führt der Kernel keinen aus. Stattdessen wird der Hardware mitgeteilt, dass sich die Maschine im Leerlauf befindet (was zu einem geringeren Stromverbrauch führt).

Prozesse, die auf den Abschluss der E / A warten, werden normalerweise im Status D in z . B. psund angezeigt top.


Ich habe mehrere Prozesse mit etwa 10% des gesamten Speichers gestartet. Mir ist aufgefallen, dass sich viele von ihnen im D-Zustand befinden. Liegt dies an der langsamen E / A auf diesem bestimmten Computer? Angenommen, ich habe 9 Prozesse, sie konkurrieren möglicherweise um E / A und viele von ihnen befinden sich im D-Zustand.
Kemin Zhou

@KeminZhou Im Vergleich zu CPU-Geschwindigkeiten ist die E / A ziemlich langsam - sogar die schnelle E / A. Ein einzelner E / A-schwerer Prozess kann eine Magnetplatte, sogar eine SSD, problemlos belegen. 10 E / A-schwere Prozesse könnten einige beschäftigen.
Derobert

1

Ja, die Aufgabe wird im Systemaufruf read () blockiert. Eine andere Aufgabe, die bereit ist, wird ausgeführt, oder wenn keine anderen Aufgaben bereit sind, wird die inaktive Aufgabe (für diese CPU) ausgeführt.

Ein normaler, blockierender Disc-Lesevorgang bewirkt, dass die Task in den Status "D" wechselt (wie andere angemerkt haben). Solche Aufgaben tragen zum Lastdurchschnitt bei, obwohl sie nicht die CPU verbrauchen.

Einige andere Arten von E / A, insbesondere ttys und network, verhalten sich nicht ganz gleich - der Prozess endet im Status "S" und kann unterbrochen werden und zählt nicht zum Lastdurchschnitt.



0

Im Allgemeinen wird der Prozess blockiert. Wenn sich der Lesevorgang in einem Dateiskriptor befindet, der als nicht blockierend markiert ist, oder wenn der Prozess asynchrone E / A verwendet, wird er nicht blockiert. Auch wenn der Prozess andere Threads hat, die nicht blockiert sind, können sie weiter ausgeführt werden.

Die Entscheidung, welcher Prozess als nächstes ausgeführt wird, liegt beim Scheduler im Kernel.

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.