Por que o cpu_idle é chamado como a última função da rotina start_kernel?

3

Estou lendo a função start_kernel em% código%. A última função chamada em /init/main.c é start_kernel e, no final de rest_init , rest_init é chamada.

Por que é chamada como a última função da rotina cpu_idle e o que ela faz?

    
por Anthony 23.02.2018 / 23:04

2 respostas

5

Para responder sua primeira pergunta,

What does cpu_idle do?

Em geral (sem considerar o contexto da questão), quando a CPU está em um estado ocioso, significa que o kernel atualmente não tem trabalho para a CPU executar, e assim a CPU está aguardando mais trabalho o kernel.

Você pode pensar em como o kernel funciona como um gerenciador, dando trabalho à CPU (de acordo com uma programação). Quando não houver trabalho disponível para a CPU assumir, a CPU será colocada em um estado ocioso e aguardará uma interrupção. Você pode ler mais sobre interupções de CPU aqui .

Com relação ao contexto de sua pergunta, você pode ler a implementação exata do que cpu_idle faz:

cpu_idle(void)
{
    set_thread_flag(TIF_POLLING_NRFLAG);

    while (1) {
        /* FIXME -- EV6 and LCA45 know how to power down
           the CPU.  */

        while (!need_resched())
            cpu_relax();
        schedule();
    }
}

Em resumo, cpu_idle coloca a CPU em um estado em que ela está inativa. Isso é obtido usando while loops para manipular o agendamento de processos quando necessário; mais, a CPU fica ociosa com cpu_relax .

Why is it called as the last function of the start_kernel routine?

O motivo pelo qual esta função é executada como a última instrução na rotina start_kernel é porque a CPU executou todo o trabalho necessário para iniciar o kernel - nenhuma instrução adicional será executada, assim a CPU ficará inativa, aguardando a próxima tarefa ou interromper. Para indicar isso, a CPU deve ser colocada em um estado inativo, já que não é mais necessário para a inicialização do kernel.

    
por 23.02.2018 / 23:50
2

Uma unidade central de processamento sempre precisa estar executando algo . Se não houver nada para fazer, ele simplesmente faz um loop infinito, que uma interrupção (como a interrupção de heartbeat do sistema) irá separá-lo.

Em sistemas operacionais multiprocessos / multithreads mais antigos, se o dispatcher (o planejador de baixo nível que escolhe e alterna para o próximo thread para executar a fila de threads executáveis) não encontrar um thread pronto para executá-lo, basta digitar um loop tão infinito.

Este é um problema para sistemas operacionais multi- processador , no entanto, como o loop infinito é executado no contexto de qualquer thread que o dispatcher estava deixando. Isso pode acabar com o mesmo segmento "executando" em dois processadores ao mesmo tempo, o que causa uma série de problemas.

Portanto, um design mais recente (comparativamente mais recente, isto é, como essa ideia tem algumas décadas) era ter, para cada processador no sistema, um thread ocioso . Este thread não faz nada além de loop indefinidamente e é sempre executável. Portanto, sempre há um thread que o dispatcher pode escolher, e nunca há uma situação em que não exista um thread executável para a execução de um processador.

Nas versões antigas do Unix real, quando a inicialização do sistema foi concluída, o código de inicialização configurou estruturas de dados descrevendo-o como processo # 0. Este tem o nome tradicional do "processo swapper", devido ao que ele fez. Tinha que fazer algo após a inicialização ter terminado, então o que ele fez foi executar o código que trocou os segmentos de processo entre a RAM principal e a área de troca do DASD.

A idéia de troca desapareceu no final dos anos 1970, com o advento dos designs de paginação sob demanda; e o processo # 0 tornou-se primeiro o processo ocioso e depois o processo do sistema que continha todos os threads ociosos .

E é isso que também está acontecendo no Linux.

Naturalmente, o gerenciamento de energia tem sido considerado por mais de um quarto de século neste ponto, e o ciclo infinito tradicional de uma instrução de ramificação incondicional que se ramifica a si próprio causa muito trabalho desnecessário e perda de energia. Os encadeamentos ociosos modernos (novamente um termo relativo) invocam instruções especiais do processador que instruem o processador em execução a aguardar, diminuindo potencialmente sua taxa de clock para economizar energia, para que ele receba uma interrupção de hardware. (Ao longo dos anos, arquiteturas de instruções x86 mudaram de hlt para pause , também conhecido como rep nop , negociando a liberação completa de recursos por um núcleo de execução dentro de um processador "hyperthreaded" para toques de ombro entre processadores que não envolvem interrupções, efetivamente transformando threads inativas em garçons perpétuos para um bloqueio de giro.)

Leitura adicional

por 24.02.2018 / 11:36