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

Funktionsweise des Linux-Prozesslebenszyklus – Eltern-, Kind- und Init-Prozess

Ein Prozess ist nichts anderes als eine laufende Instanz eines Programms. Es wird auch als Programm in Aktion definiert.

Das Konzept eines Prozesses ist ein grundlegendes Konzept eines Linux-Systems. Prozesse können andere Prozesse erzeugen, andere Prozesse beenden, mit anderen Prozessen kommunizieren und vieles mehr.

In diesem Tutorial besprechen wir den Lebenszyklus eines Prozesses und gehen auf verschiedene Aspekte ein, die ein Prozess in seinem Lebenszyklus durchläuft.

1. Code vs. Programm vs. Prozess

Lassen Sie uns zuerst den Unterschied zwischen Code, Programm und Prozess verstehen.

Code: Es folgt ein Codebeispiel:

#include <stdio.h>
#include <unistd.h>

int main(void)
{
    printf("\n Hello World\n");
    sleep(10);

    return 0;
}

Speichern wir den obigen Codeabschnitt in einer Datei namens helloWorld.c. Diese Datei wird also zu Code.

Programm: Wenn der Code nun kompiliert wird, erzeugt er eine ausführbare Datei. So wird der obige Code kompiliert:

$ gcc -Wall helloWorld.c -o helloWorld

Dies würde eine ausführbare Datei namens helloWorld erzeugen. Diese ausführbare Datei wird als Programm bezeichnet.

Prozess: Lassen Sie uns nun diese ausführbare Datei ausführen:

$ ./helloWorld 

 Hello World

Nach der Ausführung wird ein Prozess erstellt, der dieser ausführbaren Datei (oder diesem Programm) entspricht. Dieser Prozess führt den gesamten Maschinencode aus, der im Programm enthalten war. Aus diesem Grund wird ein Prozess als laufende Instanz eines Programms bezeichnet.

Um die Details des neu erstellten Prozesses zu überprüfen, führen Sie den Befehl ps folgendermaßen aus:

$ ps -aef | grep hello*
1000      6163  3017  0 18:15 pts/0    00:00:00 ./helloWorld

Um die Ausgabe des ps-Befehls zu verstehen, lesen Sie unseren Artikel über 7 ps-Befehlsbeispiele.

2. Eltern-Kind-Prozess

Jeder Prozess hat einen übergeordneten Prozess und kann untergeordnete Prozesse haben oder auch nicht. Nehmen wir das eins nach dem anderen. Betrachten Sie die Ausgabe des Befehls ps auf meinem Ubuntu-Rechner:

1000      3008     1  0 12:50 ?        00:00:23 gnome-terminal
1000      3016  3008  0 12:50 ?        00:00:00 gnome-pty-helper
1000      3017  3008  0 12:50 pts/0    00:00:00 bash
1000      3079  3008  0 12:58 pts/1    00:00:00 bash
1000      3321     1  0 14:29 ?        00:00:12 gedit
root      5143     2  0 17:20 ?        00:00:04 [kworker/1:1]
root      5600     2  0 17:39 ?        00:00:00 [migration/1]
root      5642     2  0 17:39 ?        00:00:00 [kworker/u:69]
root      5643     2  0 17:39 ?        00:00:00 [kworker/u:70]
root      5677     2  0 17:39 ?        00:00:00 [kworker/0:2]
root      5680     2  0 17:39 ?        00:00:00 [hci0]
root      5956   916  0 17:39 ?        00:00:00 /sbin/dhclient -d -sf /usr/lib/NetworkManager/nm-dhcp-client.action -pf /run/sendsigs.
root      6181     2  0 18:35 ?        00:00:00 [kworker/1:0]
root      6190     2  0 18:40 ?        00:00:00 [kworker/1:2]
1000      6191  3079  0 18:43 pts/1    00:00:00 ps -aef

Ganzzahlen in der zweiten und dritten Spalte der obigen Ausgabe stellen die Prozess-ID und die übergeordnete Prozess-ID dar. Beachten Sie die fett markierten Zahlen. Als ich den Befehl „ps -aef“ ausführte, wurde ein Prozess erstellt, seine Prozess-ID ist 6191. Sehen Sie sich nun die Elternprozess-ID an, es ist 3079. Wenn Sie zum Anfang der Ausgabe schauen, sehen Sie diese ID 3079 ist die Prozess-ID des Bash-Prozesses. Dies bestätigt, dass die Bash-Shell die übergeordnete Shell für jeden Befehl ist, den Sie durchlaufen.

Auch für Prozesse, die nicht über die Shell erstellt werden, gibt es einen übergeordneten Prozess. Führen Sie einfach den Befehl „ps -aef“ auf Ihrem Linux-Rechner aus und beobachten Sie die Spalte PPID (Elternprozess-ID). Sie werden darin keinen leeren Eintrag sehen. Dies bestätigt, dass jeder Prozess einen übergeordneten Prozess hat.

Kommen wir nun zu den untergeordneten Prozessen. Immer wenn ein Prozess einen anderen Prozess erstellt, wird ersterer als übergeordneter Prozess bezeichnet, während letzterer als untergeordneter Prozess bezeichnet wird. Technisch gesehen wird ein untergeordneter Prozess erstellt, indem die Funktion fork() innerhalb des Codes aufgerufen wird. Wenn Sie einen Befehl von der Shell aus ausführen, folgt normalerweise auf die Funktion fork() eine Reihe von Funktionen exec().

Wir haben besprochen, dass jeder Prozess einen übergeordneten Prozess hat. Dies kann die Frage aufwerfen, was mit einem untergeordneten Prozess geschieht, dessen übergeordneter Prozess beendet wird. Nun, das ist eine gute Frage, aber kommen wir später darauf zurück.

3. Der Init-Prozess

Wenn das Linux-System gestartet wird, wird als erstes vmlinuz in den Speicher geladen. Es ist die komprimierte ausführbare Datei des Linux-Kernels. Dies führt zur Erstellung des Init-Prozesses. Dies ist der erste Prozess, der erstellt wird. Der Init-Prozess hat eine PID von eins und ist der übergeordnete übergeordnete Prozess aller Prozesse in einer Linux-Sitzung. Wenn Sie die Linux-Prozessstruktur als Baum betrachten, dann ist init der Startknoten dieses Baums.

Um zu bestätigen, dass init der erste Prozess ist, können Sie den Befehl pstree auf Ihrer Linux-Box ausführen. Dieser Befehl zeigt den Prozessbaum für eine Linux-Sitzung an.

Hier ist eine Beispielausgabe:

init-+-NetworkManager-+-dhclient
     |                |-dnsmasq
     |                `-3*[{NetworkManager}]
     |-accounts-daemon---2*[{accounts-daemon}]
     |-acpid
     |-at-spi-bus-laun-+-dbus-daemon
     |                 `-3*[{at-spi-bus-laun}]
     |-at-spi2-registr---{at-spi2-registr}
     |-avahi-daemon---avahi-daemon
     |-bamfdaemon---3*[{bamfdaemon}]
     |-bluetoothd
     |-colord---{colord}
     |-console-kit-dae---64*[{console-kit-dae}]
     |-cron
     |-cups-browsed
     |-cupsd
     |-2*[dbus-daemon]
     |-dbus-launch
     |-dconf-service---2*[{dconf-service}]
     |-evince---3*[{evince}]
     |-evinced---{evinced}
     |-evolution-sourc---2*[{evolution-sourc}]
     |-firefox-+-plugin-containe---16*[{plugin-containe}]
     |         `-36*[{firefox}]
     |-gconfd-2
     |-gedit---3*[{gedit}]
     |-6*[getty]
     |-gnome-keyring-d---7*[{gnome-keyring-d}]
     |-gnome-terminal-+-bash
     |                |-bash-+-less
     |                |      `-pstree
     |                |-gnome-pty-helpe
     |                `-3*[{gnome-terminal}]
     |-gvfs-afc-volume---2*[{gvfs-afc-volume}]
     |-gvfs-gphoto2-vo---{gvfs-gphoto2-vo}
     |-gvfs-mtp-volume---{gvfs-mtp-volume}
     |-gvfs-udisks2-vo---{gvfs-udisks2-vo}
     |-gvfsd---{gvfsd}
     |-gvfsd-burn---2*[{gvfsd-burn}]
     |-gvfsd-fuse---4*[{gvfsd-fuse}]
     ...
     ...
     ...

Die Ausgabe bestätigt, dass sich init ganz oben im Prozessbaum befindet. Wenn Sie den fettgedruckten Text beachten, sehen Sie auch die vollständige Eltern-Kind-Beziehung des pstree-Prozesses. Lesen Sie mehr über pstree in unserem Artikel über Baum und pstree.

Kommen wir nun auf die Frage zurück (die wir im letzten Abschnitt offen gelassen haben) über die Konsequenzen, wenn der Elternprozess beendet wird, während das Kind noch lebt. Nun, in diesem Fall wird das Kind offensichtlich verwaist, aber vom Init-Prozess adoptiert. Der Init-Prozess wird also zum neuen Elternprozess der untergeordneten Prozesse, deren Eltern beendet werden.

4. Prozesslebenszyklus

In diesem Abschnitt werden wir den Lebenszyklus eines normalen Linux-Prozesses besprechen, bevor er beendet und aus der Kernel-Prozesstabelle entfernt wird.

  • Wie bereits erwähnt, wird ein neuer Prozess durch fork() erstellt und wenn eine neue ausführbare Datei ausgeführt werden soll, wird die exec()-Familie von Funktionen nach fork() aufgerufen. Sobald dieser neue Prozess erstellt ist, wird er in die Warteschlange der laufbereiten Prozesse eingereiht.
  • Wenn nur fork() aufgerufen wurde, dann ist es sehr wahrscheinlich, dass der neue Prozess im Benutzermodus läuft, aber wenn exec() aufgerufen wird, wird der neue Prozess im Kernelmodus laufen, bis ein neuer Prozessadressraum dafür erstellt wird.
  • Während der Prozess läuft, kann ihm ein Prozess mit höherer Priorität durch einen Interrupt zuvorkommen. In diesem Fall wird der vorgezogene Prozess erneut in die Warteschlange der laufbereiten Prozesse gestellt. Dieser Prozess wird zu einem späteren Zeitpunkt vom Scheduler übernommen.
  • Ein Prozess kann während der Ausführung in den Kernelmodus wechseln. Dies ist möglich, wenn auf eine Ressource wie eine Textdatei zugegriffen werden muss, die auf der Festplatte gespeichert ist. Da Operationen mit Zugriff auf Hardware einige Zeit in Anspruch nehmen können, ist es sehr wahrscheinlich, dass der Prozess in den Ruhezustand wechselt und erst dann wieder aufwacht, wenn die angeforderten Daten verfügbar sind. Wenn der Prozess aufgeweckt wird, bedeutet dies nicht, dass er sofort mit der Ausführung beginnt, er wird erneut in die Warteschlange gestellt und zur geeigneten Zeit vom Scheduler zur Ausführung ausgewählt.
  • Ein Prozess kann auf viele Arten beendet werden. Es kann die Funktion exit() zum Beenden aufrufen oder Linux-Signale zum Beenden verarbeiten. Außerdem können einige Signale nicht abgefangen werden und führen dazu, dass der Prozess sofort beendet wird.
  • Es gibt verschiedene Arten von Linux-Prozessen. Sobald der Prozess beendet ist, wird er nicht vollständig eliminiert. Ein Eintrag, der einige diesbezügliche Informationen enthält, wird in der Adresstabelle des Kernel-Prozesses aufbewahrt, bis der übergeordnete Prozess explizit die Funktionen wait() oder waitpid() aufruft, um den Beendigungsstatus des untergeordneten Prozesses zu erhalten. Bis der übergeordnete Prozess dies tut, wird der beendete Prozess als Zombie-Prozess bezeichnet.

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

  2. So starten Sie den Linux-Befehl im Hintergrund und trennen den Prozess im Terminal

  3. So installieren Sie vtop unter Linux

  4. Wie kann man einen untergeordneten Prozess sterben lassen, nachdem der übergeordnete Prozess beendet wurde?

  5. Wie verschiebe ich Dateien und Verzeichnisse in den übergeordneten Ordner in Linux?

So zeigen Sie PPIDs unter Linux an

So arbeiten Sie mit Vordergrund- und Hintergrundprozessen unter Linux

Wie man einen Prozess unter Linux beendet

So finden Sie die PID und PPID eines Prozesses in Linux

So beenden Sie Prozesse in Linux mit kill, killall und pkill

So verfolgen und verfolgen Sie einen Linux-Prozess