Estou pesquisando diferentes fontes, mas não consigo encontrar uma boa descrição da anatomia da criança que colhe. Este é um caso simples do que eu gostaria de 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 que o zumbi está esperando a criança?
Você pode explicar este? Preciso conhecer C e ler o código-fonte do Bash para entender melhor isso ou existe alguma documentação? Eu já consultei:
- vários links neste site e Stack Overflow
- A linha de comando do Linux por W. Shotts
man bash
- Manual de Referência do Bash (nos documentos de código-fonte do Bash)
- Guia Bash para Iniciantes @ tldp.org
- Guia Avançado de Bash-Scripting
Lançamento do GNU bash, versão 4.3.42 (1) (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
Respostas:
O zumbi não está esperando por seu filho. Como qualquer processo zumbi, ele permanece por aí até que seus pais o colecionem.
Você deve exibir todos os processos envolvidos para entender o que está acontecendo e examinar o PPID também. Use esta linha de comando:
O pai do processo que você está matando é
cat
. O que acontece é que o bash executa o comando backgroundcat <( sleep 100 & wait )
em um subshell. Como a única coisa que esse subshell faz é configurar algum redirecionamento e executar um comando externo, esse subshell é substituído pelo comando externo. Aqui está o resumo:fork
para executar o comandocat <( sleep 100 & wait )
em segundo plano em um filho (14247).pipe
para criar um canal e, em seguida,fork
para criar um filho para executar a substituição do processosleep 100 & wait
.fork
para ser executadosleep 100
em segundo plano. Como o neto não é interativo, o processo em segundo plano não é executado em um grupo de processos separado. Então o neto esperasleep
sair.setpgid
(é um trabalho em segundo plano em um shell interativo para obter seu próprio grupo de processos) e depoisexecve
executacat
. (Estou um pouco surpreso que a substituição do processo não esteja ocorrendo no grupo de processos em segundo plano.)cat
, que não sabe nada sobre nenhum processo filho e não tem ligações comerciaiswait
. Como o pai do neto não o colhe, o neto fica para trás como um zumbi.cat
sai - ou porque você o mata, ou porquesleep
retorna e fecha o canal paracat
ver o final de sua entrada. Nesse ponto, o pai do zumbi morre, então o zumbi é coletado pelo init e o colhe.Se você alterar o comando para
depois
cat
é executado em um processo separado, não no filho do processo original do bash: o primeiro filho precisa ficar para trás para executarecho done
. Nesse caso, se você matar o neto, ele não permanecerá como um zumbi, porque a criança (que ainda está executando o bash naquele momento) a colhe.Veja também Como o linux lida com o processo zumbi e Pode um zumbi ter órfãos? As crianças órfãs serão perturbadas ao colher o zumbi?
fonte
cat
) e não aguardando 14248 (aguardandosleep
)? Existe alguma memória de quem espera por quem, que a criança (14247) perdeu e a festança original (14246) não, ou talvez uma lista de sinais como o SIGCHLD de quem deveria ser chamado e o 14247 (agora em execuçãobash
) cancelado a assinatura com em relação a 14248?wait
seu filho, ou seja, ele o colhe. Percebo como isso seria confuso, removi a frase que não estava no ponto certo cronologicamente falando. As informações de que um processo morreu vão para o pai do processo, um processo não pode "se inscrever" para receber informações sobre a morte de outro processo.Zumbi não está esperando a criança. Em vez disso, o zumbi é o processo que já morreu (por conta própria ou foi morto - como no seu exemplo), teve seu código, dados e pilha desalocados e agora contém apenas seu código de saída, aguardando o pai chamar
wait(2)
para recuperá-lo. (e, portanto, finalmente limpe completamente a entrada do processo da tabela de processos)No seu exemplo, quando o sono termina (ou é interrompido), o pai lê os status de saída e colhe os zumbis. Veja acima mencionado
wait(2)
para detalhes.fonte