it-swarm.com.de

Linux-Prozesszustände

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

83
Blair

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

Eine Ausnahme bildet das Öffnen einer Datei (z. B. eines Terminals oder eines anderen Zeichengeräts) im Modus O_NONBLOCK, Wenn davon ausgegangen wird, dass ein Gerät (z. B. ein Modem) Zeit für die Initialisierung benötigt. Sie haben in Ihrer Frage jedoch Blockgeräte angegeben. Außerdem habe ich noch nie eine ioctl() ausprobiert, die wahrscheinlich auf einem im nicht blockierenden Modus geöffneten fd blockiert (zumindest nicht wissentlich).

Wie ein anderer Prozess ausgewählt wird, hängt ganz von dem von Ihnen verwendeten Scheduler ab sowie davon, welche anderen Prozesse möglicherweise dazu beigetragen haben, die Gewichtung innerhalb dieses Schedulers 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 sind normalerweise in Gruppen mit anderen "Zombies" zusammengefasst, aber der Begriff wäre nicht korrekt, da sie technisch nicht mehr funktionieren.

80
Tim Post

Wenn ein Prozess Daten von einer Festplatte abrufen muss, stoppt er die Ausführung auf der CPU, 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 Userspace" genannt) spricht man von einem blockierenden Systemaufruf . Wenn Sie write(2) aufrufen (ein dünner libc-Wrapper um den gleichnamigen Systemaufruf), stoppt Ihr Prozess nicht genau an dieser Grenze. Im Kernel wird weiterhin der Systemaufrufcode ausgeführt. Meist geht es bis zu einem bestimmten Treiber für den Festplattencontroller (Dateiname → Dateisystem/VFS → Blockgerät → Gerätetreiber), bei dem ein Befehl zum Abrufen eines Blockes auf der Festplatte an die richtige Hardware gesendet wird Schneller Betrieb meistens.

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

Im Userspace kehrt der blockierende Systemaufruf mit dem richtigen Status und den richtigen Daten zurück, und der Programmablauf wird fortgesetzt.

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

Die meisten Antworten, die hier den D-Status (der in den Linux-Statusnamen als TASK_UNINTERRUPTIBLE Bezeichnet wird) erwähnen, sind falsch. Der Zustand [~ # ~] d [~ # ~] ist ein spezieller Schlafmodus, der nur in einem Kernel-Space-Code-Pfad ausgelöst wird, wenn dieser Code vorliegt Pfad kann nicht unterbrochen werden (weil es zu komplex für die Programmierung wäre), mit der Erwartung, dass es nur für eine sehr kurze Zeit blockiert. Ich glaube, dass die meisten "D-Zustände" eigentlich unsichtbar sind; Sie sind sehr kurzlebig und können mit Sampling-Tools wie 'top' nicht beobachtet werden.

In einigen Situationen können im D-Zustand unstillbare Prozesse auftreten. NFS ist dafür berühmt, und ich habe es oft angetroffen. 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 Fehler-Timeout bei einigen 100 ms liegen) und NFS, das tatsächlich Daten aus dem Netzwerk abruft ist widerstandsfähiger und hat eine langsame Wiederherstellung (eine TCP Zeitüberschreitung von 300 Sekunden ist üblich). Lesen Sie diesen Artikel für die in Linux 2.6.25 eingeführte coole Lösung mit dem Status TASK_KILLABLE. Vor dieser Ära gab es einen Hack, bei dem Sie tatsächlich Signale an NFS-Prozess-Clients senden konnten, indem Sie ein SIGKILL an den Kernel-Thread rpciod sendeten, aber vergessen Sie diesen hässlichen Trick.

123
zerodeux

Ein Prozess, der E/A ausführt, wird in den Zustand D versetzt (unterbrechungsfreier Ruhezustand) , wodurch die CPU freigegeben wird, bis ein Hardware-Interrupt auftritt, der die CPU auffordert, dies zu tun kehren Sie zur Ausführung des Programms zurück. Sehen man ps für die anderen Prozesszustände.

Abhängig von Ihrem Kernel gibt es einen Prozess-Scheduler , der eine Liste von Prozessen aufzeichnet, die zur Ausführung bereit sind. Zusammen mit einem Planungsalgorithmus teilt er dem Kernel mit, welcher Prozess welcher CPU zugewiesen werden soll. Es sind Kernel- und Benutzerprozesse zu berücksichtigen. Jedem Prozess wird eine Zeitscheibe zugewiesen. Dies ist ein Teil der CPU-Zeit, die er verwenden darf. Sobald der Prozess seine gesamte Zeitscheibe verwendet, wird er als abgelaufen markiert und im Planungsalgorithmus mit einer niedrigeren Priorität versehen.

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

7
user224579

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

Um Prozesse im D-Status 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 ermitteln, können Sie einen Befehl ähnlich dem folgenden Beispiel verwenden (ersetzen Sie 31134 durch die Nummer des Sleeping-Prozesses):

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

Ich stellte fest, dass die Eingabe des Befehls umount mit der Option -f (force) in das zugehörige angehängte nfs-Dateisystem den Ruhezustand aufwecken konnte:

umount -f /auto/pippo

das Dateisystem wurde nicht ausgehängt, da es ausgelastet war. Der zugehörige Prozess wurde jedoch aktiviert und ich konnte das Problem lösen, ohne einen Neustart durchführen zu müssen.

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

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

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

1
MarkR

Angenommen, Ihr Prozess ist ein einzelner Thread und Sie verwenden das Blockieren von E/A. Ihr Prozess blockiert 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 der Computer im Leerlauf ist (was zu einem geringeren Stromverbrauch führt).

Prozesse, die auf den Abschluss der E/A warten, werden normalerweise in Zustand D angezeigt, z. B. in ps und top.

1
derobert

Ja, Aufgaben, die auf IO warten, werden blockiert und andere Aufgaben werden ausgeführt. Die Auswahl der nächsten Aufgabe erfolgt durch den Linux-Scheduler .

0

Im Allgemeinen wird der Prozess blockiert. Befindet sich der Lesevorgang in einem Dateideskriptor, der als nicht blockierend markiert ist, oder verwendet der Prozess asynchron IO=), wird er nicht blockiert. Auch wenn der Prozess andere Threads hat, die nicht blockiert sind, werden diese nicht blockiert kann weiterlaufen.

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

0
Benno