O que um programa faz quando envia um sinal SIGKILL?
772
Quando eu killall -9 namematava um programa, o estado se tornava zumbi. Alguns minutos depois, parou de verdade. Então, o que está acontecendo durante esses minutos?
Na verdade, o programa nunca recebe o sinal SIGKILL, pois o SIGKILL é totalmente tratado pelo sistema operacional/kernel.
Quando o SIGKILL para um processo específico é enviado, o escalonador do kernel imediatamente para de dar a esse processo mais tempo de CPU para executar o código do espaço do usuário. Se o processo tiver alguma thread executando código de espaço do usuário em outras CPUs/núcleos no momento em que o escalonador tomar essa decisão, essas threads também serão interrompidas. (Em sistemas de núcleo único, isso costumava ser muito mais simples: se o único núcleo de CPU no sistema estivesse executando o escalonador, por definição, ele não estava executando o processo ao mesmo tempo!)
Se o processo/thread estiver executando o código do kernel (por exemplo, uma chamada do sistema ou uma operação de E/S associada a um arquivo mapeado na memória) no momento do SIGKILL, fica um pouco mais complicado: apenas algumas chamadas do sistema são interrompíveis, então o O kernel marca internamente o processo como estando em um estado especial "morrendo" até que as chamadas do sistema ou as operações de E/S sejam resolvidas. O tempo de CPU para resolvê-los será agendado como de costume. Chamadas de sistema interruptíveis ou operações de E/S verificarão se o processo que as chamou está morrendo em algum ponto de parada adequado e sairá mais cedo nesse caso. As operações ininterruptas serão concluídas e verificarão um estado "morrendo" antes de retornar ao código do espaço do usuário.
Uma vez que as rotinas do kernel em processo são resolvidas, o estado do processo é alterado de "morrendo" para "morto" e o kernel começa a limpá-lo, semelhante a quando um programa é encerrado normalmente. Quando a limpeza estiver concluída, um código de resultado maior que 128 será atribuído (para indicar que o processo foi morto por um sinal; veja esta resposta para os detalhes confusos ) e o processo fará a transição para o estado "zumbi" . O pai do processo morto será notificado com um sinal SIGCHLD.
Como resultado, o próprio processo nunca terá a chance de realmente processar as informações de que recebeu um SIGKILL.
Quando um processo está em um estado "zumbi", significa que o processo já está morto, mas seu processo pai ainda não reconheceu isso lendo o código de saída do processo morto usando a wait(2)chamada do sistema. Basicamente, o único recurso que um processo zumbi está consumindo é um slot na tabela de processos que contém seu PID, o código de saída e algumas outras "estatísticas vitais" do processo no momento de sua morte.
Se o processo pai morre antes de seus filhos, os processos filhos órfãos são automaticamente adotados pelo PID #1, que tem o dever especial de continuar chamando wait(2)para que quaisquer processos órfãos não permaneçam como zumbis.
Se demorar vários minutos para um processo zumbi ser limpo, isso sugere que o processo pai do zumbi está com problemas ou não está fazendo seu trabalho corretamente.
Há uma descrição irônica sobre o que fazer em caso de problemas de zumbis em sistemas operacionais do tipo Unix: "Você não pode fazer nada pelos próprios zumbis, pois eles já estão mortos. Em vez disso, mate o mestre zumbi do mal! " (ou seja, o processo pai dos zumbis problemáticos)
Na verdade, o programa nunca recebe o sinal SIGKILL, pois o SIGKILL é totalmente tratado pelo sistema operacional/kernel.
Quando o SIGKILL para um processo específico é enviado, o escalonador do kernel imediatamente para de dar a esse processo mais tempo de CPU para executar o código do espaço do usuário. Se o processo tiver alguma thread executando código de espaço do usuário em outras CPUs/núcleos no momento em que o escalonador tomar essa decisão, essas threads também serão interrompidas. (Em sistemas de núcleo único, isso costumava ser muito mais simples: se o único núcleo de CPU no sistema estivesse executando o escalonador, por definição, ele não estava executando o processo ao mesmo tempo!)
Se o processo/thread estiver executando o código do kernel (por exemplo, uma chamada do sistema ou uma operação de E/S associada a um arquivo mapeado na memória) no momento do SIGKILL, fica um pouco mais complicado: apenas algumas chamadas do sistema são interrompíveis, então o O kernel marca internamente o processo como estando em um estado especial "morrendo" até que as chamadas do sistema ou as operações de E/S sejam resolvidas. O tempo de CPU para resolvê-los será agendado como de costume. Chamadas de sistema interruptíveis ou operações de E/S verificarão se o processo que as chamou está morrendo em algum ponto de parada adequado e sairá mais cedo nesse caso. As operações ininterruptas serão concluídas e verificarão um estado "morrendo" antes de retornar ao código do espaço do usuário.
Uma vez que as rotinas do kernel em processo são resolvidas, o estado do processo é alterado de "morrendo" para "morto" e o kernel começa a limpá-lo, semelhante a quando um programa é encerrado normalmente. Quando a limpeza estiver concluída, um código de resultado maior que 128 será atribuído (para indicar que o processo foi morto por um sinal; veja esta resposta para os detalhes confusos ) e o processo fará a transição para o estado "zumbi" . O pai do processo morto será notificado com um sinal SIGCHLD.
Como resultado, o próprio processo nunca terá a chance de realmente processar as informações de que recebeu um SIGKILL.
Quando um processo está em um estado "zumbi", significa que o processo já está morto, mas seu processo pai ainda não reconheceu isso lendo o código de saída do processo morto usando a
wait(2)
chamada do sistema. Basicamente, o único recurso que um processo zumbi está consumindo é um slot na tabela de processos que contém seu PID, o código de saída e algumas outras "estatísticas vitais" do processo no momento de sua morte.Se o processo pai morre antes de seus filhos, os processos filhos órfãos são automaticamente adotados pelo PID #1, que tem o dever especial de continuar chamando
wait(2)
para que quaisquer processos órfãos não permaneçam como zumbis.Se demorar vários minutos para um processo zumbi ser limpo, isso sugere que o processo pai do zumbi está com problemas ou não está fazendo seu trabalho corretamente.
Há uma descrição irônica sobre o que fazer em caso de problemas de zumbis em sistemas operacionais do tipo Unix: "Você não pode fazer nada pelos próprios zumbis, pois eles já estão mortos. Em vez disso, mate o mestre zumbi do mal! " (ou seja, o processo pai dos zumbis problemáticos)