Que fait un programme lorsqu'il envoie le signal SIGKILL?

39

Quand j'avais l'habitude killall -9 namede tuer un programme, l'État devenait un zombie. Quelques minutes plus tard, ça s'est vraiment arrêté. Alors, que se passe-t-il pendant ces minutes?

haïkun il
la source

Réponses:

66

En réalité, le programme ne reçoit jamais le signal SIGKILL, car SIGKILL est entièrement géré par le système d'exploitation / le noyau.

Lorsque SIGKILL est envoyé pour un processus spécifique, le planificateur du noyau arrête immédiatement de lui donner plus de temps CPU pour exécuter du code d'espace utilisateur. Si le processus a des threads exécutant le 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 simple cœur, 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 le 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, la situation devient un peu plus délicate: seuls certains appels système sont interruptibles. Le noyau en interne marque le processus comme étant dans un état de "mort" spécial jusqu'à ce que les appels système ou les opérations d'E / S soient résolus. Le temps de calcul nécessaire pour les résoudre sera programmé 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 meurt à un point d'arrêt approprié, et se terminera plus tôt dans ce cas. Les opérations ininterruptibles s'achèveront et vérifieront l'état "en voie de disparition" juste avant de revenir au code d'espace utilisateur.

Une fois que toutes les routines du noyau en cours de traitement sont résolues, l'état du processus passe de "en train de mourir" à "en arrêt" et le noyau commence à le nettoyer, comme c'est le cas lorsqu'un programme se ferme 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 compliqués ) et le processus passera à l'état "zombie". . Le parent du processus tué sera informé par un signal SIGCHLD.

En conséquence, le processus lui-même n'aura jamais l'occasion de traiter réellement les informations qu'il a reçues d'un SIGKILL.

Lorsqu'un processus est dans un état "zombie", cela signifie que le processus est déjà mort, mais que son processus parent ne l'a pas encore reconnu en lisant le code de sortie du processus mort à l'aide de l' wait(2)appel système. Fondamentalement, la seule ressource qu'un processus zombie consomme est un emplacement dans la table de processus qui contient son PID, le code de sortie et quelques autres "statistiques vitales" du processus au moment de son décès.

Si le processus parent meurt avant ses enfants, les processus enfants orphelins sont automatiquement adoptés par le PID n ° 1, qui a le devoir spécial de continuer à appeler wait(2)pour que tout processus orphelin ne reste pas sous la forme de zombies.

Si le processus d'un zombie prend plusieurs minutes à se dégager, cela suggère que le processus parent du zombie se débat ou ne fait pas son travail correctement.

Dans les systèmes d'exploitation de type Unix, il existe une description ironique qui explique ce qu'il faut faire en cas de problèmes de zombies: "Vous ne pouvez rien faire pour les zombies eux-mêmes, car ils sont déjà morts. Au lieu de cela, tuez le méchant maître des zombies! " (ie le processus parent des zombies gênants)

telcoM
la source
5
Que se passe-t-il si le processus se trouve dans un appel du noyau (par exemple, faire des E / S) lorsque SIGKILL est envoyé?
vertiges
9
@gidds Soit l'E / S sera annulée afin d'exécuter le SIGKILL, soit le SIGKILL sera retardé jusqu'à la fin de l'E / S. C'est la différence entre les états de sommeil 'S' et 'D' dans ps: 'S' est pour I / O attend que le noyau puisse annuler afin de fournir un signal, et 'D' pour ceux qu'il ne peut pas.
Zwol
6
Il n'est pas tout à fait exact de dire que le programme cesse immédiatement de donner le temps CPU au processus. Ce processus traite toujours le côté noyau de la gestion du signal, mais ce processus n’exécutera que le code du noyau, vous avez donc raison de dire que le programme ne reçoit jamais le signal. Le processus exécutera le code du noyau responsable de la majeure partie du nettoyage des ressources (fichiers ouverts, mémoire virtuelle, etc.). La dernière étape de ce code de nettoyage consiste à modifier l'état du processus en zombie et à appeler le planificateur. Ensuite, cela ne sera plus jamais programmé.
Kasperd
4
@gidds Il existe au moins quatre états différents dans lesquels le processus peut se dérouler. Il peut s'agir du code du noyau en cours d'exécution ou de la veille dans l'un des trois états de veille différents. Les états de sommeil peuvent être soit interruptibles, non interruptibles ou non interruptibles, sauf en cas de signaux mortels. S'il est en sommeil non interruptible, il restera endormi aussi longtemps qu'il le faudra et il ne pourra mourir que s'il se réveille. S'il se trouvait dans l'un des deux autres états de veille, il sera immédiatement réveillé et planifié dès qu'il y aura un processeur disponible.
Kasperd
2
@gidds Ce qui se passe ensuite dépend du code du noyau qu'il était en train d'exécuter. Peu importe qu’il soit déjà en cours d’exécution ou qu’il ait d’abord dû être réveillé pour pouvoir ensuite exécuter le code du noyau dans lequel il se trouvait à l’époque, il sera autorisé à continuer. Et ce code de noyau est responsable de remarquer que le processus a été dit de mourir et d'agir en conséquence. La plupart du temps, la bonne façon de traiter cela dans le code du noyau consiste à simplement renvoyer une erreur à partir de la fonction exécutée. Une fois que la pile d'appels du noyau a été déroulée, le code de traitement du signal peut prendre le relais juste avant de revenir au mode utilisateur.
Kasperd