No Linux, o que acontece com o estado de um processo quando ele precisa ler blocos de um disco? Está bloqueado? Em caso afirmativo, como outro processo é escolhido para execução?
Enquanto espera por read()
ou write()
para / de um retorno do descritor de arquivo, o processo será colocado em um tipo especial de hibernação, conhecido como "D" ou "Disk Sleep". Isso é especial, porque o processo não pode ser eliminado ou interrompido enquanto estiver em tal estado. Um processo esperando por um retorno de ioctl () também seria colocado em hibernação dessa maneira.
Uma exceção a isso é quando um arquivo (como um terminal ou outro dispositivo de caractere) é aberto no O_NONBLOCK
modo, passado quando é assumido que um dispositivo (como um modem) precisará de tempo para inicializar. No entanto, você indicou dispositivos de bloqueio em sua pergunta. Além disso, nunca experimentei um ioctl()
que provavelmente bloquearia em um fd aberto no modo sem bloqueio (pelo menos não conscientemente).
Como outro processo é escolhido depende inteiramente do planejador que você está usando, bem como do que outros processos podem ter feito para modificar seus pesos dentro desse planejador.
Alguns programas de espaço do usuário, em certas circunstâncias, permanecem nesse estado para sempre, até serem reinicializados. Eles são normalmente agrupados com outros "zumbis", mas o termo não seria correto, pois eles não estão tecnicamente extintos.
Quando um processo precisa buscar dados de um disco, ele efetivamente para de funcionar na CPU para permitir que outros processos sejam executados porque a operação pode levar muito tempo para ser concluída - pelo menos 5 ms de tempo de busca por um disco é comum, e 5 ms são 10 milhões Ciclos de CPU, uma eternidade do ponto de vista do programa!
Do ponto de vista do programador (também chamado de "no espaço do usuário"), isso é chamado de chamada de sistema de bloqueio . Se você chamar
write(2)
(que é um wrapper de libc fino em torno da chamada do sistema de mesmo nome), seu processo não para exatamente nesse limite; ele continua, no kernel, executando o código de chamada do sistema. Na maioria das vezes, ele vai até um driver de controlador de disco específico (nome do arquivo → sistema de arquivos / VFS → dispositivo de bloco → driver de dispositivo), onde um comando para buscar um bloco no disco é submetido ao hardware apropriado, que é muito operação rápida na maioria das vezes.ENTÃO o processo é colocado no estado de hibernação (no espaço do kernel, o bloqueio é chamado de hibernação - nada é 'bloqueado' do ponto de vista do kernel). Ele será ativado assim que o hardware finalmente buscar os dados apropriados, então o processo será marcado como executável e será agendado. Eventualmente, o planejador executará o processo.
Finalmente, no espaço do usuário, a chamada do sistema de bloqueio retorna com o status e os dados adequados e o fluxo do programa continua.
É possível invocar a maioria das chamadas de sistema de E / S no modo sem bloqueio (consulte
O_NONBLOCK
emopen(2)
efcntl(2)
). Nesse caso, as chamadas do sistema retornam imediatamente e apenas relatam o envio da operação do disco. O programador terá que verificar explicitamente em um momento posterior se a operação foi concluída, com êxito ou não, e buscar seu resultado (por exemplo, comselect(2)
). Isso é chamado de programação assíncrona ou baseada em eventos.A maioria das respostas aqui mencionando o estado D (que é chamado
TASK_UNINTERRUPTIBLE
nos nomes dos estados do Linux) está incorreta. O estado D é um modo de hibernação especial que só é acionado em um caminho de código de espaço do kernel, quando esse caminho de código não pode ser interrompido (porque seria muito complexo para programar), com a expectativa de que bloquearia apenas por um tempo curto. Eu acredito que a maioria dos "estados D" são realmente invisíveis; eles têm vida muito curta e não podem ser observados por ferramentas de amostragem como 'top'.Você pode encontrar processos impossíveis de matar no estado D em algumas situações. NFS é famoso por isso, e eu o encontrei muitas vezes. Eu acho que há um conflito semântico entre alguns caminhos de código VFS, que assumem sempre alcançar os discos locais e detecção rápida de erros (em SATA, um tempo limite de erro seria em torno de alguns 100 ms), e NFS, que realmente busca dados da rede que é mais resiliente e tem recuperação lenta (um tempo limite de TCP de 300 segundos é comum). Leia este artigo para a solução interessante introduzida no Linux 2.6.25 com o
TASK_KILLABLE
estado. Antes desta era, havia um hack onde você poderia realmente enviar sinais para clientes de processo NFS enviando um SIGKILL para o thread do kernelrpciod
, mas esqueça esse truque feio.…fonte
/proc/stat
?Um processo realizando I / O será colocado no estado D (ininterrupta hibernação) , o que libera a CPU até que haja uma interrupção de hardware que diga à CPU para retornar à execução do programa. Veja
man ps
para os outros estados do processo.Dependendo do seu kernel, existe um agendador de processos , que mantém o controle de uma fila de execução de processos prontos para execução. Ele, junto com um algoritmo de escalonamento, informa ao kernel qual processo atribuir a qual CPU. Existem processos do kernel e processos do usuário a serem considerados. Cada processo é alocado em uma fatia de tempo, que é uma parte do tempo da CPU que ele pode usar. Uma vez que o processo usa todo o seu intervalo de tempo, ele é marcado como expirado e recebe prioridade mais baixa no algoritmo de escalonamento.
No kernel 2.6 , há um escalonador de complexidade de tempo O (1) , portanto, não importa quantos processos você tenha em execução, ele atribuirá CPUs em tempo constante. Porém, é mais complicado, uma vez que o 2.6 introduziu a preempção e o balanceamento de carga da CPU não é um algoritmo fácil. Em qualquer caso, é eficiente e as CPUs não ficarão ociosas enquanto você espera pelo I / O.
fonte
Como já explicado por outros, os processos no estado "D" (ininterrupto sleep) são responsáveis pelo travamento do processo ps. Para mim, isso aconteceu muitas vezes com o RedHat 6.xe com os diretórios home NFS montados automaticamente.
Para listar processos no estado D, você pode usar os seguintes comandos:
Para saber o diretório atual do processo e, talvez, o disco NFS montado que apresenta problemas, você pode usar um comando semelhante ao exemplo a seguir (substitua 31134 pelo número do processo em espera):
Descobri que dar o comando umount com a opção -f (forçar) ao sistema de arquivos nfs montado relacionado foi capaz de despertar o processo de hibernação:
o sistema de arquivos não foi desmontado porque estava ocupado, mas o processo relacionado foi ativado e eu consegui resolver o problema sem reiniciar.
fonte
Assumindo que seu processo é um único thread e que você está usando o bloqueio de E / S, seu processo irá bloquear esperando a conclusão da E / S. O kernel escolherá outro processo para executar nesse ínterim com base na gentileza, prioridade, tempo da última execução, etc. Se não houver outros processos executáveis, o kernel não executará nenhum; em vez disso, ele dirá ao hardware que a máquina está ociosa (o que resultará em menor consumo de energia).
Os processos que estão aguardando a conclusão da E / S normalmente aparecem no estado D em, por exemplo,
ps
etop
.fonte
Sim, a tarefa é bloqueada na chamada de sistema read (). Outra tarefa que está pronta é executada, ou se nenhuma outra tarefa estiver pronta, a tarefa ociosa (para aquela CPU) é executada.
Uma leitura normal de bloqueio do disco faz com que a tarefa entre no estado "D" (como outros notaram). Essas tarefas contribuem para a média de carga, embora não estejam consumindo a CPU.
Alguns outros tipos de IO, especialmente ttys e rede, não se comportam da mesma forma - o processo termina no estado "S" e pode ser interrompido e não é contabilizado na média de carga.
fonte
Sim, as tarefas que aguardam IO são bloqueadas e outras tarefas são executadas. A seleção da próxima tarefa é feita pelo agendador Linux .
fonte
Geralmente, o processo será bloqueado. Se a operação de leitura estiver em um descritor de arquivo marcado como sem bloqueio ou se o processo estiver usando E / S assíncrona, ele não bloqueará. Além disso, se o processo tiver outros threads que não estão bloqueados, eles podem continuar em execução.
A decisão de qual processo será executado em seguida cabe ao planejador no kernel.
fonte