Warum wartet ein Zombie auf sein Kind?


11

Ich stöbere in verschiedenen Quellen, kann aber keine gute Beschreibung der Anatomie des Erntens von Kindern finden. Dies ist ein einfacher Fall von dem, was ich verstehen möchte.

$ cat <( sleep 100 & wait ) &
[1] 14247
$ ps ax -O pgid | grep $$
12126 12126 S pts/17   00:00:00 bash
14248 12126 S pts/17   00:00:00 bash
14249 12126 S pts/17   00:00:00 sleep 100
14251 14250 S pts/17   00:00:00 grep --color=auto 12126
$ kill -2 14248

$ ps ax -O pgid | grep $$
12126 12126 S pts/17   00:00:00 bash
14248 12126 Z pts/17   00:00:00 [bash] <defunct>
14249 12126 S pts/17   00:00:00 sleep 100
14255 14254 S pts/17   00:00:00 grep --color=auto 12126

Warum wartet der Zombie auf das Kind?

Kannst du das erklären? Muss ich C kennen und den Bash-Quellcode lesen, um dies besser zu verstehen, oder gibt es eine Dokumentation? Ich habe bereits konsultiert:

GNU Bash, Version 4.3.42 (1) -Veröffentlichung (x86_64-pc-linux-gnu)

Linux 4.4.0-31-generic # 50-Ubuntu SMP Mi Jul 13 00:07:12 UTC 2016 x86_64 x86_64 x86_64 GNU / Linux


2
Sollte beachten, dass dies wirklich nichts mit Bash zu tun hat (abgesehen von der Tatsache, dass, wenn Sie Bash als Shell verwenden, viele Prozesse damit gestartet werden). Andere Shells (tcsh, ksh, zsh & c) starten alle Prozesse und führen im Wesentlichen dieselben Betriebssystemfunktionen aus, um mit ihnen umzugehen.
Jamesqf

@ Jamesqf Interessant. Wenn Sie Ihren Kommentar zu einer vollwertigen Antwort erweitern möchten, wäre das großartig.

1
Abgesehen davon, dass es nicht wirklich eine Antwort ist, sondern nur darauf hinweisen, dass Sie an den falschen Stellen nach der Antwort gesucht haben :-) Jedes gute Buch über * nix-Systemprogrammierung sollte eine viel bessere Antwort liefern, als ich schreiben könnte.
Jamesqf

Antworten:


17

Der Zombie wartet nicht auf sein Kind. Wie bei jedem Zombie-Prozess bleibt er so lange bestehen, bis seine Eltern ihn einsammeln.

Sie sollten alle beteiligten Prozesse anzeigen, um zu verstehen, was vor sich geht, und auch die PPID betrachten. Verwenden Sie diese Befehlszeile:

ps -t $(tty) -O ppid,pgid

Das übergeordnete Element des Prozesses, den Sie beenden, ist cat. Was passiert ist, dass bash den Hintergrundbefehl cat <( sleep 100 & wait )in einer Subshell ausführt. Da diese Subshell nur eine Umleitung einrichten und dann einen externen Befehl ausführen muss, wird diese Subshell durch den externen Befehl ersetzt. Hier ist der Überblick:

  • Die ursprüngliche Bash (12126) ruft forkauf, um den Hintergrundbefehl cat <( sleep 100 & wait )in einem Kind (14247) auszuführen.
    • Das untergeordnete Element (14247) ruft pipeauf, um eine Pipe forkzu erstellen und anschließend ein untergeordnetes Element zum Ausführen der Prozessersetzung zu erstellen sleep 100 & wait.
      • Das Enkelkind (14248) ruft forkan, um sleep 100im Hintergrund zu rennen . Da das Enkelkind nicht interaktiv ist, wird der Hintergrundprozess nicht in einer separaten Prozessgruppe ausgeführt. Dann wartet das Enkelkind daraufsleep den Ausstieg.
    • Das Kind (14247) ruft auf setpgid(es ist ein Hintergrundjob in einer interaktiven Shell, damit es eine eigene Prozessgruppe erhält) und führt es dann execveaus cat. (Ich bin etwas überrascht, dass die Prozessersetzung in der Hintergrundprozessgruppe nicht stattfindet.)
  • Du tötest das Enkelkind (14248). Das übergeordnete Element wird ausgeführt cat, das nichts über einen untergeordneten Prozess weiß und keine geschäftlichen Anrufe hat wait. Da die Eltern des Enkels es nicht ernten, bleibt das Enkelkind als Zombie zurück.
  • Beendet schließlich cat- entweder weil Sie es töten oder weil sleepdie Pipe zurückkehrt und schließt, sodass catdas Ende ihrer Eingabe angezeigt wird. Zu diesem Zeitpunkt stirbt der Elternteil des Zombies, sodass der Zombie von init gesammelt wird und init ihn erntet.

Wenn Sie den Befehl in ändern

{ cat <( sleep 100 & wait ); echo done; } &

wird dann catin einem separaten Prozess ausgeführt, nicht im untergeordneten Element des ursprünglichen Bash-Prozesses: Das erste untergeordnete Element muss zurückbleiben, um ausgeführt zu werden echo done. In diesem Fall bleibt das Enkelkind, wenn Sie es töten, nicht als Zombie eingeschaltet, da das Kind (das zu diesem Zeitpunkt noch Bash ausführt) es erntet.

Siehe auch Wie behandelt Linux den Zombie-Prozess und kann ein Zombie Waisen haben? Werden die Waisenkinder durch das Ernten des Zombies gestört?


Ich war auch überrascht über die Prozessgruppensache. Es sieht so aus, als wäre es ein Fehler gewesen und er ist jetzt im Bash-Master-Zweig behoben.
PSkocik

"Die ursprüngliche Bash wartet auf ihr Kind (14247)." Warum oder auf welche Weise? Das Kind soll im Hintergrund laufen und es gibt keinen expliziten Anruf. Was ist der Unterschied zwischen der ursprünglichen Bash (14246), die auf 14247 wartet, und 14247 (die ausgeführt wird cat), die nicht auf 14248 wartet (auf die sie wartet sleep)? Gibt es eine Erinnerung daran, wer auf wen wartet, was das Kind (14247) verloren hat und die ursprüngliche Bash (14246) nicht, oder vielleicht eine Liste von Signalen wie SIGCHLD, von denen angerufen werden soll und von denen 14247 (jetzt läuft bash) abgemeldet werden soll Grüße zu 14248?

1
@tomas Ich meinte, dass die ursprüngliche Bash waitsein Kind anruft , dh es erntet es. Ich kann sehen, wie verwirrend das wäre. Ich habe diesen Satz entfernt, der chronologisch gesehen nicht einmal am richtigen Punkt war. Die Information, dass ein Prozess gestorben ist, geht an das übergeordnete Element dieses Prozesses. Ein Prozess kann nicht „abonnieren“, um Informationen über den Tod eines anderen Prozesses zu erhalten.
Gilles 'SO - hör auf böse zu sein'

6

Zombie wartet nicht auf das Kind. Stattdessen ist Zombie der Prozess, der bereits gestorben ist (von sich aus oder wurde getötet - wie in Ihrem Beispiel), dessen Code, Daten und Stapel freigegeben wurden und der jetzt nur noch seinen Exit-Code enthält und darauf wartet, dass sein übergeordnetes Element aufruft, wait(2)um ihn abzurufen (und damit den Prozesseintrag endgültig aus der Prozesstabelle entfernen)

In Ihrem Beispiel liest der Elternteil nach Beendigung des Schlafes (oder nach dem Tod) den Ausgangsstatus und erntet die Zombies. Siehe oben wait(2)für Details.

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.