Je fouille dans différentes sources, mais je ne trouve pas une bonne description de l'anatomie de la récolte des enfants. Ceci est un cas simple de ce que je voudrais comprendre.
$ 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
Pourquoi le zombie attend l'enfant?
Pouvez-vous expliquer celui-ci? Dois-je connaître C et lire le code source de Bash pour mieux comprendre cela ou existe-t-il une documentation? J'ai déjà consulté:
- divers liens sur ce site et Stack Overflow
- La ligne de commande Linux par W. Shotts
man bash
- Manuel de référence Bash (dans les documents de code source Bash)
- Guide Bash pour les débutants @ tldp.org
- Guide avancé de Bash-Scripting
GNU bash, version 4.3.42 (1) -release (x86_64-pc-linux-gnu)
Linux 4.4.0-31-generic # 50-Ubuntu SMP Wed Jul 13 00:07:12 UTC 2016 x86_64 x86_64 x86_64 GNU / Linux
Réponses:
Le zombie n'attend pas son enfant. Comme tout processus zombie, il reste jusqu'à ce que son parent le récupère.
Vous devez afficher tous les processus impliqués pour comprendre ce qui se passe et regarder également le PPID. Utilisez cette ligne de commande:
Le parent du processus que vous tuez est
cat
. Ce qui se passe, c'est que bash exécute la commande d'arrière-plancat <( sleep 100 & wait )
dans un sous-shell. Étant donné que la seule chose que ce sous-shell fait est de configurer une redirection puis d'exécuter une commande externe, ce sous-shell est remplacé par la commande externe. Voici le récapitulatif:fork
pour exécuter la commande d'arrière-plancat <( sleep 100 & wait )
dans un enfant (14247).pipe
pour créer un canal, puisfork
pour créer un enfant pour exécuter la substitution de processussleep 100 & wait
.fork
à s'exécutersleep 100
en arrière-plan. Étant donné que le petit-enfant n'est pas interactif, le processus d'arrière-plan ne s'exécute pas dans un groupe de processus distinct. Puis le petit-enfant attendsleep
de sortir.setpgid
(c'est un travail d'arrière-plan dans un shell interactif donc il obtient son propre groupe de processus), puis ilexecve
s'exécutecat
. (Je suis un peu surpris que la substitution de processus ne se produise pas dans le groupe de processus d'arrière-plan.)cat
, qui ne connaît aucun processus enfant et n'a aucun appel professionnelwait
. Étant donné que le parent du petit-enfant ne le récolte pas, le petit-enfant reste comme un zombie.cat
quitte - soit parce que vous le tuez, soit parce quesleep
retourne et ferme le tuyau afin decat
voir la fin de son entrée. À ce stade, le parent du zombie meurt, donc le zombie est récupéré par init et init le récolte.Si vous changez la commande en
cat
s'exécute ensuite dans un processus distinct, et non dans l'enfant du processus bash d'origine: le premier enfant doit rester derrière pour s'exécuterecho done
. Dans ce cas, si vous tuez le petit-enfant, il ne reste pas un zombie, car l'enfant (qui exécute toujours bash à ce moment-là) le récolte.Voir aussi Comment Linux gère-t-il le processus zombie et Un zombie peut-il avoir des orphelins? Les enfants orphelins seront-ils dérangés en récoltant le zombie?
la source
cat
) n'attendant pas 14248 (en attentesleep
)? Y a-t-il un souvenir de qui attend qui, que l'enfant (14247) a perdu et que le bash original (14246) n'a pas, ou peut-être une liste de signaux comme SIGCHLD qui devrait être appelé et 14247 (en cours d'exécutionbash
) désabonné avec en ce qui concerne 14248?wait
à son enfant, c'est-à-dire qu'il le récolte. Je peux voir comment cela serait déroutant, j'ai supprimé cette phrase qui n'était même pas au bon moment chronologiquement. L'information qu'un processus est mort va au parent de ce processus, un processus ne peut pas «s'abonner» pour recevoir des informations sur la mort d'un autre processus.Zombie n'attend pas l'enfant. Au lieu de cela, zombie est le processus qui est déjà mort (par lui-même, ou a été tué - comme dans votre exemple), a eu son code, ses données et sa pile désalloués, et ne contient désormais que son code de sortie, en attendant que son parent appelle
wait(2)
pour le récupérer (et donc enfin nettoyer complètement l'entrée de processus de la table de processus)Dans votre exemple, lorsque le sommeil se termine (ou est tué), le parent lira les états de sortie et récoltera les zombies. Voir ci-dessus
wait(2)
pour les détails.la source