Como o desligamento do sistema de um kernel do linux funciona internamente?

28

De alguma forma, tenho uma idéia aproximada de como o espaço do usuário e o sistema init (seja o clássico init sysV / upstart / systemd) funcionam no desligamento do sistema. (Essencialmente, há uma sucessão de ordens de "Pare!", "Por favor, pare agora mesmo", "Processo que preciso matar você para parar" e aguarde ... as coisas estão acontecendo).

De qualquer forma, eu não estou ciente de como o desligamento do sistema funciona no kernel (onde certamente também há muito o que fazer)?

Tentei examinar a documentação do kernel https://www.kernel.org/doc/htmldocs/ e até usei a ferramenta de busca da NSA para me dar uma vantagem inicial em descobrir como funciona.

Também procurei no SE U + L e não encontrei nada (eu o ignorei?)

De qualquer forma, a pergunta, embora potencialmente um pouco desafiadora, mereceria uma resposta nesta rede de perguntas e respostas, pois presumo que mais pessoas estejam interessadas em obter um esboço do que acontece no kernel do Linux no desligamento.

Potencialmente, também há alterações para vincular a algumas explicações mais detalhadas.

Uma resposta pode incluir quais chamadas do sistema e quais sinais kernais são usados?

https://github.com/torvalds/linux/blob/b3a3a9c441e2c8f6b6760de9331023a7906a4ac6/arch/x86/kernel/reboot.c parece ser o arquivo usado x86 relacionado à reinicialização (já perto de desligar, não é?)

talvez o trecho encontrado aqui http://lxr.free-electrons.com/source/kernel/reboot.c#L176 possa ser usado para dar uma explicação

176 void kernel_power_off (void)
177 {
178 kernel_shutdown_prepare (SYSTEM_POWER_OFF);
179 if (pm_power_off_prepare)
180 pm_power_off_prepare ();
181 migrate_to_reboot_cpu ();
182 syscore_shutdown ();
183 pr_emerg ("Desligar \ n");
184 kmsg_dump (KMSG_DUMP_POWEROFF);
185 machine_power_off ();
186}
187 EXPORT_SYMBOL_GPL (kernel_power_off);
humanidade e paz
fonte
8
pode o unicórnio estar com você
kiwy
11
@ Kiwy obrigado pela sugestão. Depois de algum tempo, aceitarei possíveis respostas melhores. Mas pelo menos alguma resposta já está lá.
HumanidadeANDpeace #
Não me agradeça, obrigado o unicórnio!
kiwy
Esteja ciente de que é / foi um salto para fora da janela opção para shutdown(8)isto é o obsoleto -n um que eu penso na velha documentação do UNIX usado para ler " desligar o sistema nos - a unidade central está em chamas " efetivamente um sistema confuso kill-chave que deixaria / poderia deixar bits espalhados pelo chão (ou pelo menos os sistemas de arquivos em um estado corrompido) - imaginamos que isso seria usado para um sistema do tipo quadro principal em que alguém apenas pegasse a mão em um ventilador de refrigeração. S
SlySven

Respostas:

26

Os principais recursos para entender como o kernel do Linux funciona são:

  1. A documentação .
  2. Artigos de notícias semanais do Linux .
  3. A fonte. Este é um monstro complexo que é um pouco mais fácil de entender através do LXR , a referência cruzada do Linux. A variante LXR em execução no lxr.linux.no é mais agradável que outras, mas geralmente está inativa .

Nesse caso, não consigo encontrar nada de relevante central na documentação ou no LWN, então é o LXR.

A última coisa que o código da terra do usuário faz é chamar a chamada do rebootsistema . São necessários 4 argumentos, portanto, procure SYSCALL_DEFINE4(rebootno LXR, o que leva a kernel/reboot.c. Depois de verificar os privilégios do chamador e os argumentos, o ponto de entrada syscall chama uma das várias funções: kernel_restarta reinicialização, kernel_halta parada em um loop, kernel_poweroffpara desligar o sistema, kernel_kexecpara substituir o kernel por um novo (se compilado in), ou hibernatepara salvar a memória no disco antes de desligar.

kernel_restart, kernel_haltE kernel_power_offsão bastante semelhantes:

  1. Vá até reboot_notifier_list, que é uma lista de ganchos que os componentes do kernel podem registrar para executar o código no desligamento. Apenas alguns drivers precisam executar código nesse estágio, principalmente cães de guarda.
  2. Defina a system_statevariável
  3. Desative o usermode-helper , para garantir que nenhum código de usuário seja mais iniciado. (Ainda pode haver processos existentes nesta fase.)
  4. Ligue device_shutdownpara liberar ou desligar todos os dispositivos no sistema. Muitos motoristas se conectam a esse estágio.
    Observe que qualquer sistema de arquivos que ainda esteja montado neste momento é efetivamente desmontado à força. O responsável pela chamada do sistema é responsável por qualquer desmontagem limpa.
  5. Apenas para desligar, se o ACPI estiver configurado, possivelmente execute o código para preparar a entrada no estado S5 do ACPI (desligamento suave).
  6. Em uma máquina com várias CPUs, o código pode estar em execução em qualquer CPU, o que invocou a chamada do sistema. migrate_to_reboot_cputoma o cuidado de mudar para uma CPU específica e impedir que o planejador envie código para outras CPUs. Após esse ponto, apenas uma única CPU está em execução.
  7. syscore_shutdownchama o shutdownmétodo de operações syscore registradas . Eu acho que isso é principalmente sobre desativar interrupções; alguns ganchos têm um shutdownmétodo.
  8. Registre uma mensagem informativa - a música do cisne.
  9. Finalmente, descanse de alguma maneira dependente da máquina machine_restart, chamando , machine_haltou machine_power_off.

O código de hibernação segue as seguintes etapas:

  1. Iterar através dos ganchos de gerenciamento de energia .
  2. Sincronize sistemas de arquivos.
  3. Congele todo o código do usuário .
  4. Impedir o hotplugging do dispositivo .
  5. Despejar o estado do sistema no espaço de troca.
  6. Se tudo der certo , hiberne o hardware . Isso pode envolver a chamar kernel_restart, kernel_haltou kernel_power_off, ou algum método de hibernação específico da plataforma.

Uma maneira diferente de desligar o sistema é machine_emergency_restart. Isso é chamado pela chave mágica do SysRqB . A Ochave funciona de maneira diferente: chamakernel_power_off .

O sistema também pode se transformar em pânico , ou seja, um erro irrecuperável. O pânico tenta registrar uma mensagem e, em seguida, reinicializa o sistema (por meio de um watchdog de hardware ou de uma reinicialização de emergência).

Gilles 'SO- parar de ser mau'
fonte
+1 obrigado! @Gilles se você quiser implementar algum código que limpe / desinfete a RAM da máquina como uma última etapa, registre uma operação syscore para a syscore_shutdown(ou seja, isso resolveria minha outra pergunta unix.stackexchange.com/q/122540/24394 ) . As etapas 1 e 7 permitem registrar as coisas a serem executadas no desligamento, não importando o que é o que + tive a impressão de que a ordem de execução desses retornos de chamada em (1) e (7) não pode ser influenciada! Eu vou os documentos que você mencionou, mas se você souber! obrigado!
Humanandpeace
Estou surpreso com esta pergunta e resposta não tem mais votos.
2

Esta é apenas uma resposta parcial e, com certeza, convido outras respostas, que podem ser mais exaustivas e claras.

O conteúdo desta resposta foi retirado do kernel/reboot.carquivo do kernel 3.13 linux (que pode não ser o primeiro palpite, pois o nome não é shutdown.c, mas reboot.c)

De qualquer forma, temos basicamente três funções que esboçam o processo de desligamento do sistema

  • void kernel_halt(void) // que termina com um sistema no estado de parada
  • void kernel_power_off(void) // que termina com um sistema desligado
  • void kernel_restart(char *cmd) // que finaliza o sistema para reiniciá-lo

Essas funções são muito breves e, portanto, podem ser coladas aqui na íntegra. Seu código mostra melhor quais etapas foram tomadas no caminho para o desligamento no kernel. (os comentários são meus e podem não ser 100% ideais e corretos, verifique se tem certeza. É uma tentativa simples.

void kernel_halt(void)

void kernel_halt (void)
{
    // O primeiro passo faz:
    // a) funções de chamada / retorno de chamada registradas para execução na reinicialização / desligamento
    // b) defina system_sate como SYSTEM_HALT
    // c) interrompa a interação userspacetool
    // d) chama a função device_shutdown ()
    kernel_shutdown_prepare (SYSTEM_HALT);

    // 2º passo: acho que isso é principalmente uma necessidade para sistemas com várias CPUs
    migrate_to_reboot_cpu ();

    // 3º passo:
    // syscore_shutdown - Executa todos os retornos de chamada de encerramento do núcleo do sistema registrados 
    syscore_shutdown ();

    // 4as mensagens
    pr_emerg ("Sistema interrompido \ n");
    kmsg_dump (KMSG_DUMP_HALT);

    // código da cpu-halt-code específico da 5ª chamada
    machine_halt ();
}

a coisa toda é iniciada com a sys_rebootchamada do sistema que, como não apenas reinicia, mas também encerra, não é a coisa direta a se conectar com o processo de desligamento.

humanidade e paz
fonte