Olhando para a fonte strace
, encontrei o uso da bandeira do clone, CLONE_IDLETASK
que é descrita como:
#define CLONE_IDLETASK 0x00001000 /* kernel-only flag */
Depois de analisar mais detalhadamente, descobri que, embora esse sinalizador não seja coberto, man clone
ele é realmente usado pelo kernel durante o processo de inicialização para criar processos inativos (todos com PID 0) para cada CPU na máquina. isto é, uma máquina com 8 CPUs terá pelo menos 7 (veja a pergunta abaixo) esses processos "em execução" (aspas).
Agora, isso me leva a algumas perguntas sobre o que esse processo "inativo" realmente faz. Minha suposição é que ele execute a operação NOP continuamente até o período terminar e o kernel atribua um processo real para executar ou atribuir o processo inativo novamente (se a CPU não estiver sendo usada). No entanto, esse é um palpite completo. Assim:
Em uma máquina com, digamos, 8 CPUs, 7 desses processos ociosos serão criados? (e uma CPU será mantida pelo próprio kernel enquanto nenhum trabalho do espaço do usuário estiver funcionando?)
O processo inativo é realmente apenas um fluxo infinito de operações NOP? (ou um loop que faz o mesmo).
O uso da CPU (digamos
uptime
) é simplesmente calculado por quanto tempo o processo ocioso estava na CPU e por quanto tempo ele não estava lá durante um determinado período de tempo?
PS É provável que boa parte dessa pergunta se deva ao fato de eu não entender completamente como uma CPU funciona. ou seja, eu entendo a montagem, os prazos e as interrupções, mas não sei como, por exemplo, uma CPU pode usar mais ou menos energia, dependendo do que está executando. Ficaria muito grato se alguém puder me esclarecer sobre isso também.
fonte
Respostas:
A tarefa inativa é usada para contabilização de processos e também para reduzir o consumo de energia. No Linux, uma tarefa inativa é criada para cada processador e bloqueada para esse processador; sempre que não houver outro processo para executar nessa CPU, a tarefa ociosa será agendada. O tempo gasto nas tarefas inativas aparece como tempo "inativo" em ferramentas como
top
. (O tempo de atividade é calculado de maneira diferente.)O Unix parece sempre ter tido algum tipo de loop ocioso (mas não necessariamente uma tarefa ociosa real, veja a resposta de Gilles ), e mesmo na V1 ele usava uma
WAIT
instrução que parava o processador até que ocorresse uma interrupção (significava “aguarde interromper"). Alguns outros sistemas operacionais usavam loops ocupados, DOS, OS / 2 e versões anteriores do Windows em particular. Já há muito tempo, as CPUs usam esse tipo de instrução de "espera" para reduzir o consumo de energia e a produção de calor. Você pode ver várias implementações de tarefas ociosas, por exemplo, noarch/x86/kernel/process.c
kernel Linux: a básica apenas chamaHLT
, que interrompe o processador até que ocorra uma interrupção (e ativa o modo de economia de energia C1), as outras implementações lidam com vários bugs ou ineficiências ( por exemplo, usando emMWAIT
vez deHLT
em algumas CPUs).Tudo isso é completamente separado dos estados inativos nos processos, quando eles estão aguardando um evento (E / S, etc.).
fonte
play_dead()
é um nome mnemônico muito bom para executar o HALT. Não haveria o risco de enviar HALT para cada CPU e, consequentemente, travar? (ou seja, alcançar essa situação, Halt cada CPU, seria um bug no kernel correto?)No design do livro didático de um agendador de processos, se o agendador não tiver nenhum processo para agendar (ou seja, se todos os processos estiverem bloqueados, aguardando entrada), o agendador aguardará a interrupção do processador. A interrupção pode indicar a entrada de um periférico (ação do usuário, pacote de rede, leitura concluída a partir de um disco etc.) ou pode ser uma interrupção do timer que aciona um timer no processo.
O agendador do Linux não possui código especial para um caso que não deve ser feito. Em vez disso, ele codifica o caso nada a fazer como um processo especial, o processo inativo. O processo inativo só é agendado quando nenhum outro processo é agendável (ele tem efetivamente uma prioridade infinitamente baixa). O processo inativo é de fato parte do kernel: é um thread do kernel, ou seja, um thread que executa código no kernel, em vez de código em um processo. (Mais precisamente, existe um desses threads para cada CPU.) Quando o processo inativo é executado, ele executa a operação de espera por interrupção.
O funcionamento da espera por interrupção depende dos recursos do processador. Com o design mais básico do processador, esse é apenas um loop ocupado -
O processador continua executando uma instrução de ramificação para sempre, o que não realiza nada. A maioria dos sistemas operacionais modernos não faz isso, a menos que esteja executando um processador em que não há nada melhor, e a maioria dos processadores tem algo melhor. Em vez de gastar energia sem fazer nada além de aquecer a sala, o ideal é que o processador seja desligado. Portanto, o kernel executa o código que instrui o processador a se desligar, ou pelo menos a desligar a maior parte do processador. Deve haver pelo menos uma pequena parte que permanece ligada, o controlador de interrupção. Quando um periférico aciona uma interrupção, o controlador de interrupção envia um sinal de ativação para a parte (principal) do processador.
Na prática, CPUs modernas, como Intel / AMD e ARM, têm muitas configurações complexas de gerenciamento de energia. O sistema operacional pode estimar quanto tempo o processador permanecerá no modo inativo e escolherá diferentes modos de baixo consumo de energia, dependendo disso. Os modos oferecem compromissos diferentes entre o uso de energia enquanto ocioso e o tempo necessário para entrar e sair do modo ocioso. Em alguns processadores, o sistema operacional também pode diminuir a taxa de clock do processador quando descobrir que os processos não estão consumindo muito tempo de CPU.
fonte
HLT
poderia desligar variantes do SL dos 386 e 486, antes da publicação do DX4 (o artigo da Wikipedia está incorreto).Não, uma tarefa inativa não desperdiça ciclos da CPU. O planejador simplesmente não seleciona um processo inativo para execução. Um processo inativo está aguardando a ocorrência de algum evento para que possa continuar. Por exemplo, ele pode estar aguardando entrada em uma
read()
chamada do sistema.A propósito, o kernel não é um processo separado. O código do kernel é sempre executado no contexto de um processo (bem, exceto no caso especial de um thread do kernel), portanto, não é correto dizer "e uma CPU será mantida pelo próprio kernel enquanto não estiver executando o trabalho no espaço do usuário".
fonte