Heim > Artikel > Betrieb und Instandhaltung > Es gibt verschiedene Zustände von Linux-Prozessen
Der Linux-Prozess hat 6 Zustände: 1. R ausführbarer Zustand, nur Prozesse in diesem Zustand können auf der CPU ausgeführt werden 2. S unterbrechbarer Ruhezustand, der Prozess in diesem Zustand wartet auf das Eintreten eines bestimmten Ereignisses und wird angehalten 3. D ununterbrochener Ruhezustand, der Prozess befindet sich im Ruhezustand, aber der Prozess ist in diesem Moment ununterbrochen. 4. T Pausenzustand oder Verfolgungszustand, sendet ein SIGSTOP-Signal an den Prozess und reagiert auf das Signal T-Zustand; 5. Z-Zombie-Zustand, der anzeigt, dass ein Prozess kurz vor dem Ableben steht; 6. X-Todeszustand.
Die Betriebsumgebung dieses Tutorials: Linux7.3-System, Dell G3-Computer.
Unter Linux hat ein Prozess 6 Zustände, nämlich: ausführbarer Zustand, unterbrechbarer Ruhezustand, unterbrechungsfreier Ruhezustand, angehaltener Zustand oder Verfolgungszustand, Zombie-Zustand und toter Zustand.
Detaillierte Erläuterung des Linux-Prozessstatus
Ausführbarer Status von R(TASK_RUNNING)
Nur Prozesse in diesem Status dürfen auf der CPU ausgeführt werden. Es können sich mehrere Prozesse gleichzeitig im ausführbaren Zustand befinden, und die task_struct-Strukturen (Prozesssteuerungsblöcke) dieser Prozesse werden in die ausführbare Warteschlange der entsprechenden CPU gestellt (ein Prozess kann nur in der ausführbaren Warteschlange einer CPU erscheinen). am meisten). Die Aufgabe des Prozessplaners besteht darin, einen Prozess aus der ausführbaren Warteschlange jeder CPU auszuwählen, der auf dieser CPU ausgeführt werden soll.
Viele Betriebssystemlehrbücher definieren Prozesse, die auf der CPU ausgeführt werden, als RUNNING-Zustand und Prozesse, die ausführbar sind, aber noch nicht zur Ausführung geplant sind, als READY-Zustand. Diese beiden Zustände werden unter Linux im TASK_RUNNING-Zustand vereint.
S(TASK_INTERRUPTIBLE) Unterbrechbarer Ruhezustand
Der Prozess in diesem Zustand ist angehalten, da er auf das Eintreten eines bestimmten Ereignisses wartet (z. B. Warten auf eine Socket-Verbindung, Warten auf ein Semaphor). Die task_struct-Strukturen dieser Prozesse werden in die Warteschlange der entsprechenden Ereignisse gestellt. Wenn diese Ereignisse auftreten (ausgelöst durch externe Interrupts oder durch andere Prozesse), werden ein oder mehrere Prozesse in der entsprechenden Warteschlange aktiviert.
Durch den ps-Befehl werden wir sehen, dass sich unter normalen Umständen die überwiegende Mehrheit der Prozesse in der Prozessliste im Status TASK_INTERRUPTIBLE befindet (es sei denn, die Auslastung der Maschine ist sehr hoch). Schließlich gibt es nur eine oder zwei CPUs und oft Dutzende oder Hunderte von Prozessen. Wie kann die CPU reagieren, wenn nicht die meisten Prozesse schlafen?
D(TASK_UNINTERRUPTIBLE) Ununterbrechlicher Ruhezustand
Ähnlich wie der Zustand TASK_INTERRUPTIBLE befindet sich der Prozess im Ruhezustand, aber der Prozess ist in diesem Moment unterbrechungsfrei. Unterbrechungsfrei bedeutet nicht, dass die CPU nicht auf Interrupts von externer Hardware reagiert, sondern dass der Prozess nicht auf asynchrone Signale reagiert.
In den meisten Fällen sollte ein Prozess immer in der Lage sein, auf asynchrone Signale zu reagieren, wenn er sich im Ruhezustand befindet. Andernfalls werden Sie überrascht sein, dass kill -9 einen schlafenden Prozess nicht beenden kann! So können wir auch leicht verstehen, warum die vom ps-Befehl gesehenen Prozesse selten im Status TASK_UNINTERRUPTIBLE, sondern immer im Status TASK_INTERRUPTIBLE erscheinen.
Die Bedeutung des Status TASK_UNINTERRUPTIBLE besteht darin, dass bestimmte Verarbeitungsabläufe des Kernels nicht unterbrochen werden können. Wenn Sie auf ein asynchrones Signal reagieren, wird ein Prozess zur Verarbeitung asynchroner Signale in den Ausführungsprozess des Programms eingefügt (dieser eingefügte Prozess existiert möglicherweise nur im Kernelmodus oder kann sich auf den Benutzermodus erstrecken), sodass der ursprüngliche Prozess dies tut unterbrochen werden.
Wenn der Prozess auf bestimmter Hardware ausgeführt wird (z. B. ruft der Prozess den Lesesystemaufruf auf, um eine bestimmte Gerätedatei zu lesen, und der Lesesystemaufruf führt schließlich den Code des entsprechenden Gerätetreibers aus und interagiert mit dem entsprechenden physischen Gerät), Es kann erforderlich sein, den Status TASK_UNINTERRUPTIBLE zu verwenden, um den Prozess zu schützen und zu verhindern, dass die Interaktion zwischen dem Prozess und dem Gerät unterbrochen wird und das Gerät in einen unkontrollierbaren Zustand fällt. Der Status TASK_UNINTERRUPTIBLE ist in diesem Fall immer sehr kurzlebig und grundsätzlich nicht mit dem Befehl ps zu erfassen.
Linux-Systeme verfügen außerdem über den Status TASK_UNINTERRUPTIBLE, der leicht zu erfassen ist. Nach der Ausführung des vfork-Systemaufrufs wechselt der übergeordnete Prozess in den Status TASK_UNINTERRUPTIBLE, bis der untergeordnete Prozess Exit oder Exec aufruft.
T(TASK_STPPED oder TASK_TRACED) Suspend-Status oder Trace-Status
Senden Sie ein SIGSTOP-Signal an den Prozess, und dieser wechselt als Reaktion auf das Signal in den Status TASK_STOPPED (es sei denn, der Prozess selbst befindet sich im Status TASK_UNINTERRUPTIBLE und ist nicht im Status TASK_UNINTERRUPTIBLE). auf das Signal reagieren). (SIGSTOP ist wie das SIGKILL-Signal sehr obligatorisch. Benutzerprozesse dürfen die entsprechende Signalverarbeitungsfunktion nicht über die Signalreihe von Systemaufrufen zurücksetzen.)
Durch das Senden eines SIGCONT-Signals an den Prozess kann dieser aus dem Status TASK_STOPPED wiederhergestellt werden der TASK_RUNNING-Status.
Wenn ein Prozess verfolgt wird, befindet er sich im Sonderzustand TASK_TRACED. „Verfolgt werden“ bedeutet, dass der Prozess angehalten ist und darauf wartet, dass der Prozess, der ihn verfolgt, ihn bearbeitet. Wenn Sie beispielsweise einen Haltepunkt für den verfolgten Prozess in gdb festlegen, befindet sich der Prozess im Status TASK_TRACED, wenn er am Haltepunkt stoppt. Zu anderen Zeiten befindet sich der verfolgte Prozess immer noch in den zuvor genannten Zuständen.
Für den Prozess selbst sind die Zustände TASK_STOPPED und TASK_TRACED sehr ähnlich, beide zeigen an, dass der Prozess angehalten ist.
Der Status TASK_TRACED entspricht einer zusätzlichen Schutzebene zusätzlich zu TASK_STOPPED. Der Prozess im Status TASK_TRACED kann nicht als Reaktion auf das SIGCONT-Signal aktiviert werden. Der debuggte Prozess kann nur in den Status TASK_RUNNING zurückkehren, bis der Debugging-Prozess Vorgänge wie PTRACE_CONT und PTRACE_DETACH über den Ptrace-Systemaufruf ausführt (die Vorgänge werden durch die Parameter des Ptrace-Systemaufrufs angegeben) oder der Debugging-Prozess beendet wird.
Z(TASK_DEAD - EXIT_ZOMBIE) Zombie-Status, der Prozess wird zu einem Zombie-Prozess
Der Prozess befindet sich während des Exit-Prozesses im Status TASK_DEAD.
Während dieses Exit-Prozesses werden alle vom Prozess belegten Ressourcen recycelt, mit Ausnahme der task_struct-Struktur (und einiger Ressourcen). Dem Prozess bleibt also nur die leere Hülle von task_struct übrig, weshalb er als Zombie bezeichnet wird.
Der Grund, warum task_struct beibehalten wird, liegt darin, dass task_struct den Exit-Code des Prozesses und einige statistische Informationen speichert. Und der übergeordnete Prozess wird sich wahrscheinlich um diese Informationen kümmern. Beispielsweise speichert die Variable $? in der Shell den Exit-Code des letzten beendeten Vordergrundprozesses, und dieser Exit-Code wird häufig als Beurteilungsbedingung der if-Anweisung verwendet.
Natürlich kann der Kernel diese Informationen auch an anderer Stelle speichern und die Struktur task_struct freigeben, um Platz zu sparen. Es ist jedoch bequemer, die Struktur task_struct zu verwenden, da die Suchbeziehung von pid zu task_struct im Kernel eingerichtet wurde, ebenso wie die Eltern-Kind-Beziehung zwischen Prozessen. Um die task_struct freizugeben, müssen Sie einige neue Datenstrukturen erstellen, damit der übergeordnete Prozess die Exit-Informationen seines untergeordneten Prozesses finden kann.
Der übergeordnete Prozess kann über die Wartereihe von Systemaufrufen (z. B. wait4, waitid) auf den Ausgang eines oder mehrerer untergeordneter Prozesse warten und seine Beendigungsinformationen abrufen. Dann wird durch die Wartereihe von Systemaufrufen auch der Hauptteil des untergeordneten Prozesses (task_struct) freigegeben.
Wenn der untergeordnete Prozess beendet wird, sendet der Kernel ein Signal an seinen übergeordneten Prozess, um den übergeordneten Prozess zu benachrichtigen, „die Leiche einzusammeln“. Dieses Signal ist standardmäßig SIGCHLD, aber dieses Signal kann beim Erstellen eines untergeordneten Prozesses über den Klon-Systemaufruf festgelegt werden.
Solange der übergeordnete Prozess nicht beendet wird, bleibt der untergeordnete Prozess im Zombie-Zustand immer bestehen. Wenn also der übergeordnete Prozess beendet wird, wer wird dann die „Leiche“ des untergeordneten Prozesses einsammeln?
Wenn ein Prozess beendet wird, werden alle seine untergeordneten Prozesse von anderen Prozessen gehostet (was sie zu untergeordneten Prozessen anderer Prozesse macht). Wem wird anvertraut? Dies kann der nächste Prozess in der Prozessgruppe des beendenden Prozesses (sofern vorhanden) oder Prozess Nummer 1 sein. Jeder Prozess und jeder Moment hat also einen übergeordneten Prozess. Es sei denn, es handelt sich um Prozess Nummer 1.
Prozess Nr. 1, der Prozess mit PID 1, wird auch Init-Prozess genannt. Nach dem Start des Linux-Systems ist der erste erstellte Benutzermodusprozess der Init-Prozess. Es hat zwei Aufgaben:
Führen Sie das Systeminitialisierungsskript aus und erstellen Sie eine Reihe von Prozessen (alle sind Nachkommen des Init-Prozesses);
Warten Sie in einer Endlosschleife auf das Exit-Ereignis seines untergeordneten Prozesses call waitid Der Systemaufruf wird verwendet, um die Arbeit der „Leichensammlung“ abzuschließen. Der
init-Prozess wird nicht angehalten oder beendet (dies wird vom Kernel garantiert). Es befindet sich im Status TASK_INTERRUPTIBLE, während es auf das Beenden des untergeordneten Prozesses wartet, und im Status TASK_RUNNING während des Wiederherstellungsprozesses.
X(TASK_DEAD - EXIT_DEAD) Todeszustand, der Prozess steht kurz vor der Zerstörung
Und der Prozess behält möglicherweise seine task_struct während des Exit-Prozesses nicht bei. Dieser Prozess ist beispielsweise ein abnehmbarer Prozess in einem Multithread-Programm.
Oder der übergeordnete Prozess ignoriert das SIGCHLD-Signal explizit, indem er den Handler des SIGCHLD-Signals auf SIG_IGN setzt. (Dies ist eine POSIX-Regel, obwohl das Exit-Signal des untergeordneten Prozesses auf ein anderes Signal als SIGCHLD gesetzt werden kann.)
An diesem Punkt wird der Prozess in den Exit-Status EXIT_DEAD versetzt, was bedeutet, dass der folgende Code ausgeführt wird sofort Der Prozess wird vollständig freigegeben. Daher ist der Status EXIT_DEAD sehr kurzlebig und mit dem Befehl ps kaum zu erfassen.
Der Anfangszustand des Prozesses
Der Prozess wird durch die Fork-Reihe von Systemaufrufen (Fork, Clone, Vfork) erstellt. Der Kernel (oder Kernelmodul) kann auch einen Kernelprozess über die Funktion kernel_thread erstellen . Diese Funktionen, die Unterprozesse erstellen, erfüllen im Wesentlichen die gleiche Funktion: Sie kopieren den aufrufenden Prozess, um einen Unterprozess zu erhalten. (Sie können über Optionsparameter entscheiden, ob verschiedene Ressourcen gemeinsam genutzt oder privat sind.)
Da sich der aufrufende Prozess also im Status TASK_RUNNING befindet (wie kann er sonst aufgerufen werden, wenn er nicht ausgeführt wird?), befindet sich der untergeordnete Prozess standardmäßig auch im Status TASK_RUNNING. Darüber hinaus akzeptieren der Systemaufruf clone und die Kernelfunktion kernel_thread auch die Option CLONE_STOPPED, wodurch der Anfangszustand des untergeordneten Prozesses auf TASK_STOPPED gesetzt wird.
Änderungen des Prozessstatus
Nachdem der Prozess erstellt wurde, kann der Status eine Reihe von Änderungen erfahren, bis der Prozess beendet wird. Obwohl es mehrere Prozesszustände gibt, gibt es nur zwei Richtungen für Prozesszustandsänderungen – vom TASK_RUNNING-Zustand in den Nicht-TASK_RUNNING-Zustand oder vom Nicht-TASK_RUNNING-Zustand in den TASK_RUNNING-Zustand.
Mit anderen Worten: Wenn ein SIGKILL-Signal an einen Prozess im Status TASK_INTERRUPTIBLE gesendet wird, wird der Prozess zuerst aktiviert (in den Status TASK_RUNNING wechseln) und dann als Reaktion auf das Signal SIGKILL beendet (Wechsel in den Status TASK_DEAD). Der Status TASK_INTERRUPTIBLE wird nicht direkt verlassen.
Der Prozess wechselt vom Nicht-TASK_RUNNING-Zustand in den TASK_RUNNING-Zustand, indem andere Prozesse (die auch Interrupt-Handler sein können) Weckvorgänge ausführen. Der Prozess, der das Aufwecken durchführt, setzt den Status des aufgeweckten Prozesses auf TASK_RUNNING und fügt dann seine task_struct-Struktur der ausführbaren Warteschlange einer bestimmten CPU hinzu. Dann hat der erwachte Prozess die Möglichkeit, zur Ausführung eingeplant zu werden.
Es gibt zwei Möglichkeiten für einen Prozess, vom TASK_RUNNING-Zustand in den Nicht-TASK_RUNNING-Zustand zu wechseln:
auf das Signal reagieren und in den TASK_STOPED-Zustand oder TASK_DEAD-Zustand wechseln;
Systemaufruf ausführen und aktiv in den TASK_INTERRUPTIBLE-Zustand wechseln ( oder den Status TASK_INTERRUPTIBLE oder TASK_UNINTERRUPTIBLE eingeben (z. B. Systemaufruf auswählen), da die zum Ausführen des Systemaufrufs erforderlichen Ressourcen nicht gedeckt werden können.
Offensichtlich können beide Situationen nur auftreten, wenn der Prozess auf der CPU ausgeführt wird.
... ecutable-Status und Ausführungsstatus (Status in der run_queue-Warteschlange) S
D | TASK_UNINTERRUPTIBLE | |
---|---|---|
TASK_STOPPED oder TASK_TRACED | Pause-Status oder Trace-Status, Signal kann nicht verarbeitet werden, Da überhaupt keine Zeitspanne zum Ausführen des Codes vorhanden ist | |
TASK_DEAD - EXIT_ZOMBIE | Exit-Status, wird der Prozess zu einem Zombie-Prozess. Es kann nicht getötet werden, das heißt, es reagiert nicht auf Aufgabensignale und kann nicht mit SIGKILL getötet werden. | |
Erweitertes Wissen: Was ist die Warteschlange, was ist die laufende Warteschlange, was ist Suspend/Blocking, was weckt den Prozess auf | Das Versetzen der task_struct (run_queue) aus dem laufenden Zustand in die Warteschlange wird als angehaltenes Warten (Blockieren) bezeichnet. Das Verschieben aus der Warteschlange in die laufende Warteschlange und die Planung durch die CPU wird aufgerufen Aufwecken des Prozesses | Wenn ein Prozess ausgeführt wird, weil einige seiner Betriebsbedingungen noch nicht bereit sind (z. B. ist das Netzwerk erforderlich, aber die Netzwerkkarte ist außer Betrieb, oder er muss auf E/A warten, d. h. es muss Peripheriegeräte verwenden), es wird in die Warteschlange gestellt und die Statusbits in der task_struct werden auch für S/D geändert. |
Die Warteschlange, die auf die CPU wartet, wird als laufende Warteschlange bezeichnet Die Geräte, die auf die Peripheriegeräte warten, werden als Warteschlange bezeichnet. | Der sogenannte Prozess kann sich beim Ausführen aufgrund betrieblicher Anforderungen in verschiedenen Warteschlangen befinden. In verschiedenen Warteschlangen ist der Status unterschiedlich. | Wenn sich ein Prozess im R befindet Geben Sie Folgendes an: Wenn Sie ein Peripheriegerät benötigen, das Peripheriegerät jedoch verwendet wird, ändere ich Ihren Status in S/D und stelle dann Ihre task_struct in die Warteschlange |
Linux Video Tutorial | “
Das obige ist der detaillierte Inhalt vonEs gibt verschiedene Zustände von Linux-Prozessen. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!