Come funziona l'arresto del sistema di un kernel Linux internamente?


28

Ho in qualche modo una vaga idea di come lo spazio utenti e init-system (sia esso classico init sysV / upstart / systemd) funzionino allo spegnimento del sistema. (Essenzialmente c'è una successione di ordini di "Stop!", "Per favore, fermati ora davvero", "Processo, devo ucciderti per fermarti" e aspettare ... le cose stanno succedendo).

Sono comunque ignaro di come funzioni l'arresto del sistema nel kernel (dove sicuramente ci sono anche molte cose da fare)?

Ho provato a consultare la documentazione del kernel https://www.kernel.org/doc/htmldocs/ e ho persino usato lo strumento di ricerca dell'amico della NSA per farmi capire come funziona.

Ho anche cercato su SE U + L e non ho trovato nulla (l'ho trascurato?)

Comunque la domanda, sebbene potenzialmente un po 'impegnativa, meriterebbe una risposta in questa rete di domande e risposte poiché presumo che più persone siano interessate a ottenere uno schizzo di ciò che accade nel kernel di Linux allo spegnimento.

Potenzialmente c'è anche una modifica per collegare ad alcune spiegazioni più dettagliate.

Una risposta potrebbe forse includere quali chiamate di sistema e quali segnali kernal sono utilizzati?

https://github.com/torvalds/linux/blob/b3a3a9c441e2c8f6b6760de9331023a7906a4ac6/arch/x86/kernel/reboot.c sembra essere il file x86 utilizzato relativo al riavvio (già vicino allo spegnimento, eh?)

forse lo snippet trovato qui http://lxr.free-electrons.com/source/kernel/reboot.c#L176 può essere usato per dare una spiegazione

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 ("Spegnimento \ n");
184 kmsg_dump (KMSG_DUMP_POWEROFF);
185 machine_power_off ();
186}
187 EXPORT_SYMBOL_GPL (kernel_power_off);

8
che l'unicorno sia con te
Kiwy,

1
@Kiwy grazie per il suggerimento. Accetterò dopo che è trascorso un po 'di tempo affinché possano emergere potenziali risposte migliori. Ma almeno qualche risposta è ora lì.
umanità e

Non ringraziarmi, grazie l'unicorno!
Kiwy,

Essere consapevoli del fatto che c'è / è stata saltata fuori dall'opzione della finestra , shutdown(8)cioè quella deprecata -n che penso nella vecchia documentazione di Unix utilizzata per leggere " Spegnere il sistema noi stessi - l'unità principale è IN FUOCO! " In effetti un disordinato sistema kill-switch che lascerebbe / potrebbe lasciare frammenti sparsi sul pavimento (o almeno sui file system in uno stato corrotto) - si immagina che questo sarebbe usato per un sistema di tipo main frame in cui qualcuno ha appena preso la mano in una ventola di raffreddamento. 🕱
SlySven,

Risposte:


26

Le principali risorse per capire come funziona il kernel Linux sono:

  1. La documentazione .
  2. Articoli settimanali su Linux .
  3. La fonte. Questa è una bestia complessa che è un po 'più facile da comprendere tramite LXR , il riferimento incrociato di Linux. La variante LXR in esecuzione su lxr.linux.no è più bella di altre, ma spesso è inattiva .

In questo caso, non riesco a trovare nulla di rilevante a livello centrale nella documentazione o su LWN, quindi lo è LXR.

L'ultima cosa che fa il codice utente è chiamare la rebootchiamata di sistema . Ci vogliono 4 argomenti, quindi cerca SYSCALL_DEFINE4(rebootsu LXR, che porta a kernel/reboot.c. Dopo aver controllato i privilegi del chiamante e gli argomenti, il punto di ingresso syscall chiama una delle diverse funzioni: kernel_restartper il riavvio, kernel_halta fermarsi su un loop stretto, kernel_poweroffper spegnere il sistema, kernel_kexecper sostituire il kernel con uno nuovo (se compilato in), o hibernateper salvare la memoria su disco prima di spegnersi.

kernel_restart, kernel_haltE kernel_power_offsono abbastanza simili:

  1. Passare attraverso reboot_notifier_list, che è un elenco di hook che i componenti del kernel possono registrare per eseguire il codice allo spegnimento. Solo pochi driver devono eseguire il codice in questa fase, principalmente i cani da guardia.
  2. Imposta la system_statevariabile.
  3. Disabilita usermode-helper , per assicurarti che nessun codice utente verrà più avviato. (Possono esserci ancora processi esistenti in questa fase.)
  4. Chiama device_shutdownper rilasciare o spegnere tutti i dispositivi sul sistema. Molti piloti si agganciano in questa fase.
    Si noti che tutti i filesystem che sono ancora montati a questo punto vengono effettivamente smontati forzatamente. Il chiamante della chiamata di sistema si assume la responsabilità di qualsiasi smontaggio pulito.
  5. Solo per lo spegnimento, se ACPI è configurato in, eseguire eventualmente il codice per prepararsi ad entrare nello stato ACPI S5 (soft power off).
  6. In una macchina con più CPU, il codice potrebbe essere in esecuzione su qualsiasi CPU, a prescindere dalla chiamata di sistema. migrate_to_reboot_cpusi occupa di passare a una particolare CPU e impedire allo scheduler di inviare codice su altre CPU. Dopo questo punto, è in esecuzione una sola CPU.
  7. syscore_shutdownchiama il shutdownmetodo delle operazioni di syscore registrate . Penso che si tratti principalmente di disabilitare gli interrupt; alcuni ganci hanno un shutdownmetodo.
  8. Registra un messaggio informativo: la canzone del cigno.
  9. Infine andare a riposare in qualche modo dipendente dalla macchina chiamando machine_restart, machine_halto machine_power_off.

Il codice di ibernazione passa attraverso i seguenti passaggi:

  1. Scorrere i ganci di gestione dell'alimentazione .
  2. Sincronizza i filesystem.
  3. Congela tutto il codice utente .
  4. Impedire il collegamento a caldo del dispositivo .
  5. Scarica lo stato del sistema nello spazio di scambio.
  6. Se tutto è riuscito, ibernare l'hardware . Ciò può comportare la chiamata kernel_restart, kernel_halto kernel_power_off, o qualche metodo di ibernazione specifico della piattaforma.

Un altro modo per arrestare il sistema è machine_emergency_restart. Questo è invocato dalla chiave magica SysRqB . La Ochiave funziona diversamente: chiamakernel_power_off .

Il sistema può anche spegnersi in preda al panico , ovvero un errore irrecuperabile. Il panico tenta di registrare un messaggio, quindi riavviare il sistema (tramite un watchdog hardware o un riavvio di emergenza).


+1 grazie! @Gilles se volessi implementare un codice che cancellasse / sanatizzasse la RAM della macchina come un passo di durata, registreresti un'operazione syscore per il syscore_shutdown(cioè che risolverebbe la mia altra domanda unix.stackexchange.com/q/122540/24394 ) . Il passaggio (1) e il passaggio (7) consentono entrambi di registrare roba da eseguire allo spegnimento, non di certo cos'è + Ho avuto l'impressione che l'ordine di esecuzione di quei callback in (1) e (7) non possa essere influenzato! Sarò i documenti che hai citato, ma se lo sai! Grazie!
umanità e

Sono sorpreso da questa domanda e la risposta non ha più voti.

2

Questa è solo una risposta parziale e invito sicuramente un'altra risposta, che potrebbe essere più esaustiva e chiara.

Il contenuto di questa risposta è tratto dal kernel/reboot.cfile del kernel linux 3.13 (che potrebbe non essere la prima ipotesi in quanto il nome non è shutdown.c ma reboot.c)

In ogni caso abbiamo sostanzialmente tre funzioni che disegnano il processo di spegnimento del sistema

  • void kernel_halt(void) // che termina con un sistema in stato di arresto
  • void kernel_power_off(void) // che termina con un sistema spento
  • void kernel_restart(char *cmd) // che termina il sistema per riavviarlo

Queste funzioni sono molto brevi e possono quindi essere incollate qui in modo completo. Il loro codice mostra meglio quali passi vengono fatti sulla via per l'arresto nel kernel. (i commenti sono da me e potrebbero non essere ideali e corretti al 100%, controlla te stesso per essere sicuro. È una prova semplice.

void kernel_halt(void)

void kernel_halt (void)
{
    // Il primo passo fa:
    // a) funzioni di chiamata / callback registrate per essere eseguite al riavvio / spegnimento
    // b) imposta system_sate su SYSTEM_HALT
    // c) interrompe l'interazione userspacetool
    // d) chiama la funzione device_shutdown ()
    kernel_shutdown_prepare (SYSTEM_HALT);

    // 2 ° passo: penso che ciò sia principalmente una necessità per i sistemi multi-cpu
    migrate_to_reboot_cpu ();

    // 3 ° passaggio:
    // syscore_shutdown - Esegue tutti i callback di arresto del core del sistema registrati 
    syscore_shutdown ();

    // 4 ° messaggi
    pr_emerg ("Sistema arrestato \ n");
    kmsg_dump (KMSG_DUMP_HALT);

    // Codice cpu-halt-code specifico per la quinta chiamata
    machine_halt ();
}

il tutto viene avviato con la sys_rebootchiamata di sistema che, dato che non solo si riavvia ma anche arresta, non è comunque la cosa diretta a connettersi con il processo di spegnimento.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.