Quand j'ai utilisé killall -9 name
pour tuer un programme, l'état devient zombie. Quelques minutes plus tard, ça s'est vraiment arrêté. Alors, que se passe-t-il pendant ces minutes?
En fait, le programme ne reçoit jamais le signal SIGKILL, car SIGKILL est entièrement géré par le système d'exploitation/noyau.
Lorsque SIGKILL pour un processus spécifique est envoyé, le planificateur du noyau cesse immédiatement de donner à ce processus plus de temps CPU pour exécuter le code de l'espace utilisateur. Si le processus a des threads exécutant du code d'espace utilisateur sur d'autres CPU/cœurs au moment où le planificateur prend cette décision, ces threads seront également arrêtés. (Dans les systèmes à cœur unique, cela était beaucoup plus simple: si le seul cœur de processeur du système exécutait le planificateur, par définition, il n'exécutait pas le processus en même temps!)
Si le processus/thread exécute du code du noyau (par exemple, un appel système ou une opération d'E/S associée à un fichier mappé en mémoire) au moment de SIGKILL, cela devient un peu plus délicat: seuls certains appels système sont interruptibles, donc le Le noyau marque en interne le processus comme étant dans un état spécial "en train de mourir" jusqu'à ce que les appels système ou les opérations d'E/S soient résolus. Le temps processeur pour les résoudre sera planifié comme d'habitude. Les appels système interruptibles ou les opérations d'E/S vérifieront si le processus qui les a appelés est en train de mourir à des points d'arrêt appropriés et se termineront tôt dans ce cas. Les opérations ininterrompues se termineront et vérifieront l'état "en train de mourir" juste avant de revenir au code de l'espace utilisateur.
Une fois que toutes les routines du noyau en cours sont résolues, l'état du processus passe de "en train de mourir" à "mort" et le noyau commence à le nettoyer, comme quand un programme se termine normalement. Une fois le nettoyage terminé, un code de résultat supérieur à 128 sera attribué (pour indiquer que le processus a été tué par un signal; voir cette réponse pour les détails en désordre ), et le processus passera à l'état "zombie". Le parent du processus interrompu sera averti par un signal SIGCHLD.
Par conséquent, le processus lui-même n'aura jamais la chance de traiter réellement les informations qu'il a reçues.
Lorsqu'un processus est dans un état "zombie", cela signifie que le processus est déjà mort, mais son processus parent ne l'a pas encore reconnu en lisant le code de sortie du processus mort à l'aide de l'appel système wait(2)
. Fondamentalement, la seule ressource qu'un processus zombie consomme plus est un emplacement dans la table de processus qui contient son PID, le code de sortie et d'autres "statistiques vitales" du processus au moment de sa mort.
Si le processus parent meurt avant ses enfants, les processus enfants orphelins sont automatiquement adoptés par PID # 1, qui a le devoir spécial de continuer à appeler wait(2)
afin que les processus orphelins ne restent pas comme des zombies.
S'il faut plusieurs minutes pour qu'un processus zombie s'efface, cela suggère que le processus parent du zombie a du mal ou ne fait pas son travail correctement.
Il y a une description ironique sur ce qu'il faut faire en cas de problèmes de zombies dans les systèmes d'exploitation de type Unix: "Vous ne pouvez rien faire pour les zombies eux-mêmes, car ils sont déjà morts. Au lieu de cela, tuer le méchant maître zombie! "(c'est-à-dire le processus parent des zombies gênants)