
Olhando para a fonte destrace
Encontrei o uso do sinalizador clone CLONE_IDLETASK
, descrito lá como:
#define CLONE_IDLETASK 0x00001000 /* kernel-only flag */
Depois de analisar mais profundamente, descobri que, embora esse sinalizador não seja abordado, man clone
ele é realmente usado pelo kernel durante o processo de inicialização para criar processos inativos (todos os quais devem ter PID 0) para cada CPU da máquina. ou seja, uma máquina com 8 CPUs terá pelo menos 7 (veja a pergunta abaixo) desses processos "em execução" (observe aspas).
Agora, isso me leva a algumas perguntas sobre o que esse processo "inativo" realmente faz. Minha suposição é que ele executa a operação NOP continuamente até que seu período de tempo termine e o kernel atribua um processo real para executar ou atribua o processo ocioso mais uma vez (se a CPU não estiver sendo usada). No entanto, isso é um palpite completo. Então:
Em uma máquina com, digamos, 8 CPUs, serão criados 7 desses processos ociosos? (e uma CPU será mantida pelo próprio kernel enquanto não houver trabalho no espaço do usuário?)
O processo ocioso é 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 ficou na CPU e por quanto tempo ele não esteve lá durante um determinado período de tempo?
PS É provável que grande parte desta questão se deva ao fato de eu não entender completamente como funciona uma CPU. ou seja, eu entendo a montagem, os timeframes e as interrupções, mas não sei como, por exemplo, uma CPU pode usar mais ou menos energia dependendo do que está executando. Eu ficaria grato se alguém pudesse me esclarecer sobre isso também.
Responder1
A tarefa ociosa é utilizada para contabilização de processos e também para reduzir o consumo de energia. No Linux, uma tarefa ociosa é criada para cada processador e bloqueada para esse processador; sempre que não houver outro processo para rodar naquela CPU, a tarefa ociosa é agendada. O tempo gasto em tarefas ociosas aparece como tempo “ocioso” em ferramentas como top
. (O tempo de atividade é calculado de forma diferente.)
O Unix parece sempre ter tido algum tipo de loop ocioso (mas não necessariamente uma tarefa ociosa real, vejaResposta de Gilles), e mesmo em V1usou uma WAIT
instruçãoque parava o processador até que ocorresse uma interrupção (significava “esperar pela interrupção”). Alguns outros sistemas operacionais usavam loops ocupados, DOS,SO/2e versões anteriores do Windows em particular. 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, emarch/x86/kernel/process.c
no kernel Linux: o básico apenas chamaHLT
, que para o processador até que ocorra uma interrupção (e habilita o modo de economia de energia C1), as outras implementações lidam com vários bugs ou ineficiências (por exemplousando MWAIT
em vez de HLT
em algumas CPUs).
Tudo isso é completamente separado dos estados ociosos dos processos, quando eles estão aguardando um evento (E/S etc.).
Responder2
No design clássico de um escalonador de processos, se o escalonador não tiver nenhum processo para agendar (ou seja, se todos os processos estiverem bloqueados, aguardando entrada), então o escalonador aguardará uma interrupção do processador. A interrupção pode indicar entrada de um periférico (ação do usuário, pacote de rede, leitura concluída de um disco, etc.) ou pode ser uma interrupção de temporizador que aciona um temporizador em um processo.
O agendador do Linux não possui código especial para um caso de nada fazer. Em vez disso, ele codifica o caso de não fazer nada como um processo especial, o processo ocioso. O processo ocioso só é agendado quando nenhum outro processo é escalonável (ele tem efetivamente uma prioridade infinitamente baixa). O processo ocioso é na verdade 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 thread desse tipo 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 de processador mais básico, isso é apenas um loop ocupado —
nothing:
goto nothing
O processador continua executando uma instrução de desvio para sempre, o que não resulta em nada. A maioria dos sistemas operacionais modernos não faz isso, a menos que estejam rodando em um processador onde 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 o ambiente, o ideal é desligar o processador. Portanto, o kernel executa um código que instrui o processador a desligar-se, ou pelo menos a desligar a maior parte do processador. Deve haver pelo menos uma pequena peça que permaneça ligada, o controlador de interrupção. Quando um periférico aciona uma interrupção, o controlador de interrupção enviará um sinal de ativação para o processador principal (parte dele).
Na prática, CPUs modernas como Intel/AMD e ARM possuem 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 durante o modo inativo e o tempo necessário para entrar e sair do modo inativo. Em alguns processadores, o sistema operacional também pode diminuir a frequência do processador quando descobre que os processos não estão consumindo muito tempo da CPU.
Responder3
Não, uma tarefa ociosa não desperdiça ciclos de CPU. O escalonador simplesmente não seleciona um processo ocioso para execução. Um processo ocioso está aguardando que algum evento aconteça para poder continuar. Por exemplo, pode estar aguardando entrada em uma read()
chamada de 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 houver trabalho no espaço do usuário".