Estoy investigando diferentes fuentes, pero no puedo encontrar una buena descripción de la anatomía de la cosecha infantil. Este es un caso simple de lo que me gustaría entender.
$ 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
¿Por qué el zombie está esperando al niño?
¿Puedes explicar esto? ¿Necesito saber C y leer el código fuente de Bash para obtener una comprensión más amplia de esto o hay alguna documentación? Ya he consultado:
- varios enlaces en este sitio y desbordamiento de pila
- La línea de comandos de Linux por W. Shotts
man bash
- Manual de referencia de Bash (en documentos de código fuente de Bash)
- Guía Bash para principiantes @ tldp.org
- Guía avanzada de secuencias de comandos Bash
GNU bash, versión 4.3.42 (1) -release (x86_64-pc-linux-gnu)
Linux 4.4.0-31-generic # 50-Ubuntu SMP mié 13 de julio 00:07:12 UTC 2016 x86_64 x86_64 x86_64 GNU / Linux
Respuestas:
El zombie no está esperando a su hijo. Al igual que cualquier proceso zombie, permanece hasta que su padre lo recolecte.
Debe mostrar todos los procesos involucrados para comprender lo que está sucediendo, y también mirar el PPID. Use esta línea de comando:
El padre del proceso que estás matando es
cat
. Lo que sucede es que bash ejecuta el comando de fondocat <( sleep 100 & wait )
en una subshell. Dado que lo único que hace esta subshell es configurar alguna redirección y luego ejecutar un comando externo, esta subshell se reemplaza por el comando externo. Aquí está el resumen:fork
para ejecutar el comando de fondocat <( sleep 100 & wait )
en un hijo (14247).pipe
para crear una tubería y luegofork
para crear un elemento secundario para ejecutar la sustitución del procesosleep 100 & wait
.fork
a ejecutarsesleep 100
en segundo plano. Como el nieto no es interactivo, el proceso en segundo plano no se ejecuta en un grupo de proceso separado. Entonces el nieto espera asleep
que salga.setpgid
(es un trabajo en segundo plano en un shell interactivo para que obtenga su propio grupo de procesos) y luego seexecve
ejecutacat
. (Estoy un poco sorprendido de que la sustitución del proceso no esté ocurriendo en el grupo de procesos en segundo plano).cat
, que no sabe nada sobre ningún proceso secundario y no tiene llamadas comercialeswait
. Como el padre del nieto no lo cosecha, el nieto se queda como un zombi.cat
sale, ya sea porque lo matas o porquesleep
regresa y cierra la tubería paracat
ver el final de su entrada. En ese punto, el padre del zombi muere, por lo que el zombi es recogido por init y init lo cosecha.Si cambia el comando a
luego se
cat
ejecuta en un proceso separado, no en el hijo del proceso bash original: el primer hijo tiene que quedarse atrás para ejecutarseecho done
. En este caso, si matas al nieto, no se queda como un zombie, porque el niño (que todavía está ejecutando bash en ese momento) lo cosecha.Ver también ¿Cómo asas Linux proceso de zombi y Can tiene un zombi huérfanos? ¿Se molestarán los niños huérfanos cosechando al zombi?
fuente
cat
) sin esperar 14248 (esperandosleep
)? ¿Hay algún recuerdo de quién espera a quién, qué perdió el niño (14247) y qué no lo hizo el bash original (14246), o tal vez una lista de señales como SIGCHLD de quién debería llamarse y 14247 (ahora en ejecuciónbash
) cancelado? saludos a 14248?wait
a su hijo, es decir, lo cosecha. Puedo ver cómo esto sería confuso, he eliminado esa frase que ni siquiera estaba en el punto correcto cronológicamente hablando. La información de que un proceso ha muerto va al padre de ese proceso, un proceso no puede "suscribirse" para recibir información sobre la muerte de algún otro proceso.Zombie no está esperando al niño. En cambio, zombie es el proceso que ya murió (solo o fue asesinado, como en su ejemplo), tenía su código, datos y pila desasignado, y ahora solo contiene su código de salida, esperando que su padre llame
wait(2)
para recuperarlo (y, por lo tanto, limpiar la entrada del proceso por completo de la tabla de procesos)En su ejemplo, cuando el sueño termina (o es asesinado), los padres leerán los estados de salida y cosecharán los zombis. Ver arriba mencionado
wait(2)
para más detalles.fuente