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:
- verschiedene Links auf dieser Site und Stack Overflow
- Die Linux-Kommandozeile von W. Shotts
man bash
- Bash-Referenzhandbuch (in Bash-Quellcode-Dokumenten)
- Bash Guide für Anfänger @ tldp.org
- Erweitertes Bash-Scripting-Handbuch
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
Antworten:
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:
Das übergeordnete Element des Prozesses, den Sie beenden, ist
cat
. Was passiert ist, dass bash den Hintergrundbefehlcat <( 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:fork
auf, um den Hintergrundbefehlcat <( sleep 100 & wait )
in einem Kind (14247) auszuführen.pipe
auf, um eine Pipefork
zu erstellen und anschließend ein untergeordnetes Element zum Ausführen der Prozessersetzung zu erstellensleep 100 & wait
.fork
an, umsleep 100
im 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.setpgid
(es ist ein Hintergrundjob in einer interaktiven Shell, damit es eine eigene Prozessgruppe erhält) und führt es dannexecve
auscat
. (Ich bin etwas überrascht, dass die Prozessersetzung in der Hintergrundprozessgruppe nicht stattfindet.)cat
, das nichts über einen untergeordneten Prozess weiß und keine geschäftlichen Anrufe hatwait
. Da die Eltern des Enkels es nicht ernten, bleibt das Enkelkind als Zombie zurück.cat
- entweder weil Sie es töten oder weilsleep
die Pipe zurückkehrt und schließt, sodasscat
das 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
wird dann
cat
in 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 werdenecho 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?
quelle
cat
), die nicht auf 14248 wartet (auf die sie wartetsleep
)? 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äuftbash
) abgemeldet werden soll Grüße zu 14248?wait
sein 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.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.quelle