Was macht ein Programm, wenn es ein SIGKILL-Signal sendet?

39

Wenn ich killall -9 nameein Programm tötete, wurde der Staat zum Zombie. Einige Minuten später hörte es wirklich auf. Also, was passiert in diesen Minuten?

Haikun er
quelle

Antworten:

66

Das Programm empfängt tatsächlich nie das SIGKILL-Signal, da SIGKILL vollständig vom Betriebssystem / Kernel verarbeitet wird.

Wenn SIGKILL für einen bestimmten Prozess gesendet wird, beendet der Scheduler des Kernels sofort die Bereitstellung von mehr CPU-Zeit für die Ausführung von User-Space-Code für diesen Prozess. Wenn der Prozess Threads hat, die zum Zeitpunkt der Entscheidung des Schedulers User-Space-Code auf anderen CPUs / Cores ausführen, werden diese Threads ebenfalls gestoppt. (In Single-Core-Systemen war dies früher viel einfacher: Wenn der Scheduler als einziger CPU-Kern im System ausgeführt wurde, wurde der Prozess definitionsgemäß nicht gleichzeitig ausgeführt!)

Wenn der Prozess / Thread zum Zeitpunkt von SIGKILL Kernel-Code ausführt (z. B. einen Systemaufruf oder eine E / A-Operation, die mit einer Speicherzuordnungsdatei verknüpft ist), wird es etwas kniffliger: Nur einige Systemaufrufe sind unterbrechbar Der Kernel markiert den Prozess intern als in einem speziellen "sterbenden" Zustand, bis die Systemaufrufe oder E / A-Vorgänge aufgelöst sind. Die CPU-Zeit zur Behebung dieser Probleme wird wie gewohnt eingeplant. Unterbrechbare Systemaufrufe oder E / A-Vorgänge überprüfen, ob der Prozess, der sie aufgerufen hat, an einem geeigneten Haltepunkt abstirbt, und werden in diesem Fall vorzeitig beendet. Der unterbrechungsfreie Betrieb wird abgeschlossen und kurz vor der Rückkehr zum Benutzerbereichscode auf einen "sterbenden" Zustand überprüft.

Sobald alle In-Process-Kernel-Routinen aufgelöst sind, wird der Prozessstatus von "sterbend" in "tot" geändert und der Kernel beginnt mit der Bereinigung, ähnlich wie beim normalen Beenden eines Programms. Sobald die Bereinigung abgeschlossen ist, wird ein Ergebniscode größer als 128 zugewiesen (um anzuzeigen, dass der Prozess durch ein Signal beendet wurde; die unordentlichen Details finden Sie in dieser Antwort ), und der Prozess wechselt in den Status "Zombie" . Die Eltern des getöteten Prozesses werden mit einem SIGCHLD-Signal benachrichtigt.

Infolgedessen wird der Prozess selbst niemals die Möglichkeit erhalten, die Informationen, die er als SIGKILL erhalten hat, tatsächlich zu verarbeiten.

Wenn sich ein Prozess in einem "Zombie" -Zustand befindet, bedeutet dies, dass der Prozess bereits tot ist, der übergeordnete Prozess dies jedoch noch nicht bestätigt hat, indem er den Beendigungscode des toten Prozesses mithilfe des wait(2)Systemaufrufs liest . Grundsätzlich ist die einzige Ressource, die ein Zombie-Prozess mehr verbraucht, ein Slot in der Prozesstabelle, der seine PID, den Beendigungscode und einige andere "wichtige Statistiken" des Prozesses zum Zeitpunkt seines Todes enthält.

Wenn der übergeordnete Prozess vor seinen untergeordneten Prozessen stirbt, werden die verwaisten untergeordneten Prozesse automatisch von der PID # 1 übernommen, die eine besondere Pflicht hat, weiterhin Anrufe zu tätigen, wait(2)damit verwaiste Prozesse nicht als Zombies auftreten.

Wenn es einige Minuten dauert, bis ein Zombie-Prozess beendet ist, deutet dies darauf hin, dass der übergeordnete Prozess des Zombies Probleme hat oder seinen Job nicht ordnungsgemäß ausführt.

Es gibt eine flotte Beschreibung, was bei Zombie-Problemen in Unix-ähnlichen Betriebssystemen zu tun ist: "Sie können nichts für die Zombies selbst tun, da sie bereits tot sind. Töten Sie stattdessen den bösen Zombie-Meister! " (dh der Elternprozess der lästigen Zombies)

telcoM
quelle
5
Was passiert, wenn sich der Prozess beim Senden von SIGKILL in einem Kernel-Aufruf befindet (z. B. beim Ausführen von E / A)?
gidds
9
@gidds Entweder wird die E / A abgebrochen, um den SIGKILL auszuführen, oder der SIGKILL wird verzögert, bis der E / A abgeschlossen ist. Dies ist der Unterschied zwischen "S" - und "D" -Schlafzuständen in ps: "S" steht für E / A-Wartezeiten, die der Kernel abbrechen kann, um ein Signal zu liefern, und "D" für diejenigen, die dies nicht können.
zwol
6
Es ist nicht ganz richtig zu sagen, dass der Zeitplan der Prozess-CPU-Zeit nicht mehr unmittelbar zur Verfügung steht. Die Kernel-Seite der Signalverarbeitung wird weiterhin von diesem Prozess ausgeführt, aber der Prozess führt nur Kernel-Code aus, sodass Sie Recht haben, wenn Sie sagen, dass das Programm das Signal nie empfängt. Der Prozess führt Kernel-Code aus, der für die Bereinigung der meisten Ressourcen (offene Dateien, virtueller Speicher usw.) verantwortlich ist. Die letzten Schritte dieses Bereinigungscodes bestehen darin, den Prozessstatus in Zombie zu ändern und den Scheduler aufzurufen. Dann wird es nie wieder geplant.
Kasperd
4
@gidds Es gibt mindestens vier verschiedene Zustände, in denen sich der Prozess befinden kann. Er kann derzeit Kernel-Code ausführen oder in einem von drei verschiedenen Schlafzuständen schlafen. Die Schlafzustände können außer für tödliche Signale entweder unterbrechbar, nicht unterbrechbar oder nicht unterbrechbar sein. Wenn es sich in einem ununterbrochenen Schlaf befindet, wird es so lange schlafen bleiben, wie es braucht, und erst wenn es aufwacht, hat es die Chance zu sterben. Wenn es sich in einem der beiden anderen Ruhezustände befand, wird es sofort geweckt und eingeplant, sobald eine CPU dafür verfügbar ist.
Kasperd
2
@gidds Was als nächstes passiert, hängt vom Kernel-Code ab, den es ausgeführt hat. Unabhängig davon, ob es bereits ausgeführt wurde oder erst aufgeweckt werden musste und dann den Kernel-Code ausführen konnte, in dem es sich zu der Zeit befand, kann es fortgesetzt werden. Und dieser Kernel-Code ist dafür verantwortlich zu bemerken, dass dem Prozess befohlen wurde, zu sterben und entsprechend zu handeln. Die meiste Zeit besteht der richtige Weg, mit dem im Kernelcode umzugehen, darin, einfach einen Fehler von der Funktion zurückzugeben, die sie ausgeführt hat. Sobald der Kernel-Call-Stack abgewickelt wurde, kann der Signalbehandlungscode die Funktion übernehmen, bevor er in den Benutzermodus zurückkehrt.
Kasperd