Pergunta

Às vezes, quando eu escrever um programa em Linux e deixa de funcionar devido a um bug de algum tipo, ele se tornará um processo ininterrupta e continuar a executar para sempre até que eu reiniciar o meu computador (mesmo se eu sair). Minhas perguntas são:

  • O que faz com que um processo para tornar-se ininterrupta?
  • Como faço para impedir que isso aconteça?
  • Esta é provavelmente uma pergunta estúpida, mas existe alguma maneira de interrompê-lo sem ter de reiniciar o computador?
Foi útil?

Solução

Um processo ininterrupta é um processo que acontece de estar em uma chamada de sistema (função kernel) que não pode ser interrompida por um sinal.

Para entender o que isso significa, você precisa entender o conceito de uma chamada de sistema interrompível. O exemplo clássico é read(). Esta é uma chamada de sistema que pode levar um longo tempo (segundos), uma vez que pode potencialmente envolvem girando-se um disco rígido, ou cabeças em movimento. Durante a maior parte deste tempo, o processo estará dormindo, bloqueando no hardware.

Enquanto o processo está dormindo na chamada de sistema, ele pode receber um sinal assíncrono unix (digamos, SIGTERM), em seguida, acontece o seguinte:

  • O sistema chama sai prematuramente, e está configurado para retorno -EINTR para userspace.
  • O manipulador de sinal é executado.
  • Se o processo ainda está em execução, torna-se o valor de retorno da chamada de sistema, e pode fazer a mesma chamada novamente.

Voltando início da chamada de sistema permite que o código de espaço do usuário para alterar imediatamente o seu comportamento em resposta ao sinal. Por exemplo, que encerra de forma limpa na reacção para SIGINT ou SIGTERM.

Por outro lado, algumas chamadas de sistema não estão autorizados a ser interrompido desta maneira. Se o sistema chama barracas, por algum motivo, o processo pode indefinidamente permanece neste estado unkillable.

LWN publicou uma artigo agradável que tocou o tema em julho.

Para responder à pergunta original:

  • Como evitar que isso aconteça:. Descobrir qual driver está causando-lhe problemas, e quer parar de usar, ou se tornar um hacker do kernel e corrigi-lo

  • Como matar um processo ininterrupta sem reiniciar: de alguma forma fazer a chamada de sistema terminar. Frequentemente a maneira mais eficaz de fazer isso sem bater o interruptor de alimentação é puxar o cabo de alimentação. Você também pode se tornar um hacker do kernel e fazer o uso do driver TASK_KILLABLE, como explicado no artigo LWN.

Outras dicas

Quando um processo está em modo de usuário, ele pode ser interrompido a qualquer momento (mudar para o modo kernel). Quando o kernel retorna ao modo de usuário, ele verifica se existem sinais pendentes (incluindo os que são usados ??para matar o processo, como SIGTERM e SIGKILL). Isso significa que um processo pode ser morto apenas no retorno ao modo de usuário.

A razão de um processo não pode ser morto em modo kernel é que ele poderia corromper as estruturas do kernel usado por todos os outros processos na mesma máquina (da mesma forma que matar um thread pode estruturas de dados potencialmente corruptos utilizado por outros segmentos no mesmo processo).

Quando o kernel precisa fazer algo que poderia levar um longo tempo (esperando em uma tubulação de escrita por outro processo ou esperando o hardware para fazer algo, por exemplo), ele dorme, marcando-se como dormir e chamando o programador para Mudar para outro processo (se não houver um processo não-dormindo, muda para um processo de "dummy", que conta a CPU para abrandar um pouco e senta-se em um loop - o loop ocioso).

Se um sinal é enviado para um processo de dormir, tem que ser acordado antes que ele irá retornar ao espaço do usuário e, assim, processar o sinal pendente. Aqui temos a diferença entre os dois principais tipos de sono:

  • TASK_INTERRUPTIBLE, o sono interruptível. Se uma tarefa é marcada com esta bandeira, é dormir, mas pode ser acordado por sinais. Isso significa que o código que marcou a tarefa como dormir está esperando um sinal possível, e depois que ele acorda irá verificar-lo e retorno da chamada de sistema. Após o sinal é tratado, a chamada de sistema pode potencialmente ser reiniciado automaticamente (e eu não vou entrar em detalhes sobre como isso funciona).
  • TASK_UNINTERRUPTIBLE, o sono ininterrupta. Se uma tarefa é marcada com esta bandeira, não está à espera de ser acordado por outra coisa que não seja o que está esperando, ou porque ele não pode ser facilmente reiniciado, ou porque os programas estão esperando a chamada de sistema para ser atômica. Isso também pode ser usado para dorme conhecido por ser muito curto.

TASK_KILLABLE (mencionado no artigo LWN ligado a pela resposta de DDAA) é uma nova variante.

Isso responde a sua primeira pergunta. Quanto à sua segunda pergunta: você não pode evitar dorme ininterruptas, eles são uma coisa normal (isso acontece, por exemplo, cada vez que um processo lê / escreve de / para o disco); no entanto, eles devem durar apenas uma fração de segundo. Se eles duram muito mais tempo, isso normalmente significa um problema de hardware (ou um problema de driver de dispositivo, que tem a mesma aparência para o kernel), onde o driver de dispositivo está aguardando o hardware para fazer algo que nunca vai acontecer. Também pode significar que você está usando NFS eo servidor NFS é baixo (ele está aguardando para o servidor para recuperar, você também pode usar o "intr" opção para evitar o problema)

.

Finalmente, a razão que você não pode recuperar é a mesma razão as esperas do kernel até o retorno para o modo de usuário para entregar um sinal ou matar o processo: seria estruturas de dados do kernel potencialmente corruptos (código à espera de um sono interruptível pode receber um erro que diz a ele para retornar ao espaço do usuário, onde o processo pode ser morto;. código de espera em um sono ininterrupta não está esperando qualquer erro)

processos Pilhas são geralmente espera de I / O após uma falha de página.

Considere o seguinte:

  • As tentativas de rosca para acessar uma página que não está em núcleo (ou um executável que é carregado por demanda, uma página de memória anônima que foi trocado, ou um mmap () 'arquivo d que é a demanda carregado, que são a mesma coisa)
  • O kernel está agora (tentando) carregá-lo no
  • O processo não pode continuar até que a página está disponível.

O processo / tarefa não pode ser interrompido neste estado, porque não pode lidar com quaisquer sinais; se o fizesse, outra falha de página iria acontecer e seria de volta onde estava.

Quando digo "processo", eu realmente quero dizer "tarefa", que sob Linux (2.6) traduz aproximadamente a "thread" que pode ou não pode ter uma entrada individual "grupo de discussão" em / proc

Em alguns casos, pode estar esperando por um longo tempo. Um exemplo típico disso seria onde o arquivo executável ou mmap'd está em um sistema de arquivos de rede em que o servidor falhou. Se o I / O, eventualmente, tiver êxito, a tarefa continuará. Se ele eventualmente falhar, a tarefa será geralmente obter um SIGBUS ou algo assim.

Para a sua 3ª pergunta: Eu acho que você pode matar os processos ininterruptas, executando sudo kill -HUP 1. Ele irá reiniciar o init sem terminar os processos em execução e depois executá-lo, meus processos ininterruptas tinham desaparecido.

Se você está falando de um processo de "zumbi" (que é designado como "zumbis" na saída do ps), então este é um registro inofensiva na lista de processos à espera de alguém para recolher o seu código de retorno e pode ser ignorada com segurança .

Você poderia descrever o que e "processo ininterrupta" é para você? Será que ele sobrevive o "kill -9" e felizmente chugs junto? Se for esse o caso, então é preso em algum syscall, que está preso em algum driver e você está preso com este processo até que a reinicialização (e às vezes é melhor para reiniciar em breve) ou descarga de motorista relevante (o que é improvável que isso aconteça) . Você pode tentar usar "strace" para descobrir onde o seu processo está preso e evitá-lo no futuro.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top