GNU/Linux >> LINUX-Kenntnisse >  >> Linux

Linux-Prozesszustände

Beim Warten auf read() oder write() zu/von einer Dateideskriptorrückgabe wird der Prozess in eine spezielle Art von Ruhezustand versetzt, bekannt als "D" oder "Disk Sleep". Dies ist etwas Besonderes, da der Prozess in einem solchen Zustand nicht beendet oder unterbrochen werden kann. Ein Prozess, der auf eine Rückkehr von ioctl() wartet, würde auf diese Weise ebenfalls schlafen gelegt.

Eine Ausnahme hiervon ist, wenn eine Datei (z. B. ein Terminal oder ein anderes Zeichengerät) in O_NONBLOCK geöffnet wird mode, übergeben, wenn davon ausgegangen 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 ioctl() ausprobiert das wird wahrscheinlich auf einem im nicht blockierenden Modus geöffneten fd blockieren (zumindest nicht wissentlich).

Wie ein anderer Prozess ausgewählt wird, hängt vollständig von dem von Ihnen verwendeten Scheduler ab und davon, was andere Prozesse möglicherweise getan haben, um ihre Gewichtungen 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 werden normalerweise mit anderen "Zombies" gruppiert, aber der Begriff wäre nicht korrekt, da sie technisch nicht veraltet sind.


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

Abhängig von Ihrem Kernel gibt es einen Prozessplaner , das 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 gibt Kernel-Prozesse und Benutzerprozesse, die berücksichtigt werden müssen. Jedem Prozess wird eine Zeitscheibe zugewiesen, die ein Teil der CPU-Zeit ist, die er verwenden darf. Sobald der Prozess seinen gesamten Zeitabschnitt verbraucht hat, wird er als abgelaufen markiert und erhält im Scheduling-Algorithmus eine niedrigere Priorität.

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


Wenn ein Prozess Daten von einer Festplatte abrufen muss, stoppt er effektiv die Ausführung auf der CPU, um andere Prozesse laufen zu lassen, da der Vorgang lange dauern kann – mindestens 5 ms Suchzeit für eine Festplatte sind üblich, und 5 ms sind 10 Millionen CPU-Zyklen, aus Programmsicht eine Ewigkeit!

Aus Sicht des Programmierers (auch "im Userspace" genannt) wird dies als blockierender Systemaufruf bezeichnet . Wenn Sie write(2) anrufen (was ein dünner libc-Wrapper um den gleichnamigen Systemaufruf ist), hält Ihr Prozess nicht genau an dieser Grenze an; es fährt im Kernel fort und führt den Systemaufrufcode aus. Meistens geht es bis zu einem bestimmten Festplatten-Controller-Treiber (Dateiname → Dateisystem/VFS → Blockgerät → Gerätetreiber), wo ein Befehl zum Abrufen eines Blocks auf der Festplatte an die richtige Hardware gesendet wird, was sehr schneller Betrieb die meiste Zeit.

DANN wird der Prozess in den Schlafzustand versetzt (Im Kernel-Space wird das Blockieren als Schlafen bezeichnet – aus Kernel-Sicht ist nichts jemals 'blockiert'). Es wird geweckt, sobald die Hardware endlich die richtigen Daten abgerufen hat, dann wird der Prozess als ausführbar markiert und wird terminiert. Schließlich führt der Scheduler den Prozess aus.

Schließlich im Userspace der blocking system call kehrt mit dem richtigen Status und den richtigen Daten zurück, und der Programmablauf geht weiter.

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 kehren die Systemaufrufe sofort zurück und melden nur die Übergabe der Plattenoperation. Der Programmierer muss zu einem späteren Zeitpunkt explizit prüfen, ob die Operation erfolgreich abgeschlossen wurde oder nicht, und ihr Ergebnis abrufen (z. B. mit select(2) ). Dies wird als asynchrone oder ereignisbasierte Programmierung bezeichnet.

Die meisten Antworten hier erwähnen den D-Zustand (das heißt TASK_UNINTERRUPTIBLE in den Linux-Staatsnamen) sind falsch. Das D state ist ein spezieller Schlafmodus, der nur in einem Kernelspace-Codepfad ausgelöst wird, wenn dieser Codepfad nicht unterbrochen werden kann (weil es zu komplex zu programmieren wäre), mit der Erwartung, dass es nur für sehr kurze Zeit blockieren würde. Ich glaube, dass die meisten "D-Zustände" tatsächlich unsichtbar sind; Sie sind sehr kurzlebig und können nicht von Sampling-Tools wie 'top' beobachtet werden.

In einigen Situationen können Sie auf nicht zu beendende Prozesse im D-Zustand stoßen. NFS ist dafür berühmt und mir ist es schon oft begegnet. Ich denke, es gibt einen semantischen Konflikt zwischen einigen VFS-Codepfaden, die davon ausgehen, dass sie immer lokale Festplatten und eine schnelle Fehlererkennung erreichen (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 (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_KILLABLE eingeführt wurde Zustand. 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 rpciod senden , aber vergiss diesen hässlichen Trick.…


Linux
  1. So beenden Sie einen Zombie-Prozess unter Linux

  2. Linux schneller booten

  3. Zeitsynchronisierung Linux

  4. Zeitsynchronisierung Linux

  5. Linux-Startvorgang

Pstree-Befehl unter Linux

Kill-Befehl unter Linux

Letzter Befehl in Linux

Prozessüberwachung unter Linux

Überprüfen Sie die Zeitzone in Linux

Wie man einen Prozess unter Linux beendet