Wie bei echten Zombies kann ein Zombie-Prozess nicht getötet werden, weil er bereits tot ist.
Wie es passiert
Wenn unter Linux / Unix ein Prozess stirbt / endet und alle Informationen aus dem Prozess aus dem Systemspeicher entfernt werden, bleibt nur der Prozessdeskriptor erhalten. Der Prozess wird in den Zustand Z (Zombie) versetzt. Sein übergeordneter Prozess erhält ein Signal vom Kernel: SIGCHLD
Dies bedeutet, dass einer seiner untergeordneten Prozesse beendet wird, unterbrochen wird oder nach einer Unterbrechung fortgesetzt wird (in unserem Fall wird er einfach beendet).
Der übergeordnete Prozess muss jetzt den wait()
Syscall ausführen, um den Beendigungsstatus und andere Informationen aus seinem untergeordneten Prozess zu lesen. Dann wird der Deskriptor aus dem Speicher entfernt und der Prozess ist kein Zombie mehr.
Wenn der übergeordnete Prozess den wait()
Syscall nie aufruft , bleibt der Zombie-Prozessdeskriptor im Speicher und frisst den Verstand. Normalerweise sehen Sie keine Zombie-Prozesse, da der oben beschriebene Vorgang weniger Zeit in Anspruch nimmt.
Die Morgendämmerung der Toten
Jeder Prozessdeskriptor benötigt sehr wenig Speicher, sodass einige Zombies nicht sehr gefährlich sind (wie im echten Leben). Ein Problem ist, dass jeder Zombie-Prozess seine Prozess-ID behält und ein Linux / Unix-Betriebssystem eine begrenzte Anzahl von Pids hat. Wenn eine falsch programmierte Software viele Zombie-Prozesse generiert, kann es vorkommen, dass Prozesse nicht mehr gestartet werden können, da keine Prozess-IDs mehr verfügbar sind.
Also, wenn sie in großen Gruppen sind, sind sie sehr gefährlich (wie in vielen Filmen wird sehr gut demonstriert)
Wie können wir uns gegen eine Horde Zombies verteidigen?
Ein Schuss in den Kopf würde funktionieren, aber ich kenne den Befehl dafür nicht (SIGKILL wird nicht funktionieren, weil der Prozess bereits tot ist).
Nun, Sie können SIGCHLD über kill an den übergeordneten Prozess senden, aber wenn dieses Signal ignoriert wird, was dann? Ihre einzige Möglichkeit ist, den übergeordneten Prozess zu beenden und den Zombie durch den Init-Prozess zu "adoptieren". Init ruft regelmäßig den wait()
Syscall an, um seine Zombiekinder zu säubern.
In deinem Fall
In Ihrem Fall müssen Sie SIGCHLD an den crond-Prozess senden:
root@host:~# strace -p $(pgrep cron)
Process 1180 attached - interrupt to quit
Dann von einem anderen Terminal:
root@host:~$ kill -17 $(pgrep cron)
Die Ausgabe ist:
restart_syscall(<... resuming interrupted call ...>) = ? ERESTART_RESTARTBLOCK (To be restarted)
--- SIGCHLD (Child exited) @ 0 (0) ---
wait4(-1, 0x7fff51be39dc, WNOHANG, NULL) = -1 ECHILD (No child processes) <-- Here it happens
rt_sigreturn(0xffffffffffffffff) = -1 EINTR (Interrupted system call)
stat("/etc/localtime", {st_mode=S_IFREG|0644, st_size=1892, ...}) = 0
rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0
rt_sigaction(SIGCHLD, NULL, {0x403170, [CHLD], SA_RESTORER|SA_RESTART, 0x7fd6a7e9d4a0}, 8) = 0
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
nanosleep({42, 0}, ^C <unfinished ...>
Process 1180 detached
Sie sehen, dass der wait4()
Syscall -1 ECHILD zurückgibt, was bedeutet, dass kein untergeordneter Prozess vorhanden ist. Die Schlussfolgerung lautet also: cron reagiert auf den SIGCHLD-Systemaufruf und sollte die Apokalypse nicht erzwingen.