Por que um zumbi está esperando por seu filho?

11

Eu estou cavando através de diferentes fontes, mas não consigo encontrar uma boa descrição da anatomia da criança colhendo. 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 pelo garoto?

Você pode explicar isso? Preciso saber C e ler o código-fonte do Bash para obter uma compreensão mais ampla disso ou há alguma documentação? Eu já consultei:

GNU bash, versão 4.3.42 (1) -release (x86_64-pc-linux-gnu)

Linux 4.4.0-31-genérico # 50-Ubuntu SMP Qua 13 de julho 00:07:12 UTC 2016 x86_64 x86_64 x86_64 GNU / Linux

    
por Tomasz 14.08.2016 / 23:03

2 respostas

17

O zumbi não está esperando por seu filho. Como qualquer processo de zumbi, ele fica por perto até que seu pai o colecione.

Você deve exibir todos os processos envolvidos para entender o que está acontecendo e também ver o PPID. Use esta linha de comando:

ps -t $(tty) -O ppid,pgid

O pai do processo que você está matando é cat . O que acontece é que o bash executa o comando background cat <( sleep 100 & wait ) em um subshell. Como a única coisa que essa sub-rede faz é configurar um redirecionamento e, em seguida, executar um comando externo, essa sub-tampa é substituída pelo comando externo. Aqui está o resumo:

  • O bash original (12126) chama fork para executar o comando de segundo plano cat <( sleep 100 & wait ) em um filho (14247).
    • O filho (14247) chama pipe para criar um canal e, em seguida, fork para criar um filho para executar a substituição de processo sleep 100 & wait .
      • O neto (14248) chama fork para executar sleep 100 no plano de fundo. Como o neto não é interativo, o processo em segundo plano não é executado em um grupo de processos separado. Em seguida, o neto espera que sleep saia.
    • O filho (14247) chama setpgid (é um trabalho em segundo plano em um shell interativo para obter seu próprio grupo de processos) e, em seguida, execve para executar cat . (Estou um pouco surpreso que a substituição do processo não esteja acontecendo no grupo de processos em segundo plano.)
  • Você mata o neto (14248). Seu pai está executando cat , que não sabe nada sobre qualquer processo filho e não tem nenhum negócio chamando wait . Como o pai do neto não colhe, o neto fica para trás como um zumbi.
  • Eventualmente, cat exits - seja porque você o matou ou porque sleep retorna e fecha o canal, então cat vê o final de sua entrada. Nesse ponto, o pai do zumbi morre, então o zumbi é coletado pelo init e o init o colhe.

Se você alterar o comando para

{ cat <( sleep 100 & wait ); echo done; } &

, em seguida, cat é executado em um processo separado, não no filho do processo bash original: o primeiro filho precisa ficar para trás para executar echo done . Nesse caso, se você matar o neto, ele não ficará como um zumbi, porque o filho (que ainda está em execução nesse momento) colhe o resultado.

Veja também Como o Linux lida com o processo zumbi e > Um zumbi pode ter órfãos? As crianças órfãs serão perturbadas por colher o zumbi?

    
por 14.08.2016 / 23:43
6

O zumbi não está esperando pela 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 só contém seu código de saída, esperando por seu pai para chamar wait(2) para recuperá-lo (e assim, finalmente, limpar a entrada do processo completamente da tabela de processos)

No seu exemplo, quando o sono termina (ou é eliminado), o pai lerá os status de saída e colherá os zumbis. Veja acima mencionado wait(2) para detalhes.

    
por 14.08.2016 / 23:50