Wie funktioniert das Herunterfahren eines Linux-Kernels intern?

28

Ich habe irgendwie eine ungefähre Vorstellung davon, wie der Userspace und das Init-System (sei es das klassische Init-System sysV / upstart / systemd) beim Herunterfahren des Systems funktionieren. (Im Wesentlichen gibt es eine Befehlsfolge von "Stop!", "Bitte jetzt wirklich anhalten", "Ich muss dich umbringen, um anzuhalten" und Warten ... Dinge, die sich abspielen).

Ich bin mir sowieso nicht bewusst, wie das Herunterfahren des Systems im Kernel funktioniert (wo es sicherlich auch viel zu tun gibt)?

Ich habe versucht, in der Kernel-Dokumentation https://www.kernel.org/doc/htmldocs/ nachzuschlagen, und habe sogar mit dem Kumpelsuch-Tool der NSA versucht, herauszufinden, wie es funktioniert.

Auch ich habe auf SE U + L gesucht und nichts gefunden (habe ich es übersehen?)

Die Frage, auch wenn sie möglicherweise etwas herausfordernd ist, verdient in diesem Q & A-Netzwerk eine Antwort, da ich davon ausgehe, dass mehr Leute daran interessiert sind, eine Skizze darüber zu erhalten, was beim Herunterfahren im Linux-Kernel passiert.

Möglicherweise gibt es auch Änderungen, die auf detailliertere Erklärungen verweisen.

Eine Antwort könnte vielleicht beinhalten, welche Systemaufrufe und welche Kernsignale verwendet werden?

https://github.com/torvalds/linux/blob/b3a3a9c441e2c8f6b6760de9331023a7906a4ac6/arch/x86/kernel/reboot.c scheint die für den Neustart verwendete x86-Datei zu sein (steht schon kurz vor dem Herunterfahren, oder?)

Vielleicht kann das hier gefundene Snippet http://lxr.free-electrons.com/source/kernel/reboot.c#L176 verwendet werden, um eine Erklärung zu geben

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 ("Ausschalten \ n");
184 kmsg_dump (KMSG_DUMP_POWEROFF);
185 machine_power_off ();
186}
187 EXPORT_SYMBOL_GPL (kernel_power_off);
Mensch und Frieden
quelle
8
Möge
1
@ Kiwy danke für den Vorschlag. Ich werde akzeptieren, dass nach einiger Zeit potenziell bessere Antworten aufkommen. Aber jetzt ist wenigstens eine Antwort da.
humanityANDpeace
Danke mir nicht, danke dem Einhorn!
Kiwy
Seien Sie sich bewusst, dass es eine Option zum Herausspringen des Fensters gibt / gab , shutdown(8)dh eine veraltete Option, -ndie meiner Meinung nach in der alten Unix-Dokumentation verwendet wurde, um " das System selbst herunterzufahren - die Kerneinheit ist ON FIRE! " würde / könnte Bits auf dem Boden verstreut lassen (oder zumindest die Dateisysteme in einem beschädigten Zustand) - man kann sich vorstellen, dass dies für ein System vom Typ Mainframe verwendet wird, bei dem jemand gerade seine Hand in einem Kühlventilator gefangen hat. 🕱
SlySven

Antworten:

26

Die wichtigsten Ressourcen zum Verständnis der Funktionsweise des Linux-Kernels sind:

  1. Die Dokumentation .
  2. Linux Weekly News-Artikel .
  3. Die Quelle. Dies ist ein komplexes Biest, das mit LXR , dem Linux-Querverweis, etwas einfacher zu verstehen ist. Die auf lxr.linux.no ausgeführte LXR-Variante ist besser als andere, fällt aber häufig aus.

In diesem Fall kann ich nichts zentral Relevantes in der Dokumentation oder auf LWN finden, so wie es LXR ist.

Der Userland-Code ruft zuletzt den rebootSystemaufruf auf . Es werden 4 Argumente benötigt, also suchen Sie nach SYSCALL_DEFINE4(rebootLXR, was zu führt kernel/reboot.c. Nach der Überprüfung des Anrufers Privilegien und die Argumente, ruft der syscall Einstiegspunkt eine von mehreren Funktionen: kernel_restartzum Neustart, kernel_haltum Halt auf einer engen Schleife, kernel_poweroffzu schalten Sie das System, kernel_kexecum den Kernel durch eine neue ersetzt werden (wenn kompiliert in) oder hibernateum den Speicher vor dem Ausschalten auf der Festplatte zu speichern.

kernel_restart, kernel_haltUnd kernel_power_offsind ziemlich ähnlich:

  1. Gehen Sie durch . Hierbei reboot_notifier_listhandelt es sich um eine Liste von Hooks, die Kernel-Komponenten registrieren können , um Code beim Herunterfahren auszuführen. In dieser Phase müssen nur wenige Treiber Code ausführen, meistens Watchdogs.
  2. Stellen Sie die system_stateVariable ein.
  3. Deaktivieren Usermode-Helfer , um sicherzustellen , dass kein Code Benutzer mehr gestartet. (In dieser Phase können noch Prozesse vorhanden sein.)
  4. Rufen Sie device_shutdownan, um alle Geräte im System freizugeben oder auszuschalten. Viele Fahrer schließen sich dieser Etappe an.
    Beachten Sie, dass alle Dateisysteme, die zu diesem Zeitpunkt noch eingehängt sind, zwangsweise ausgehängt werden. Der Aufrufer des Systemaufrufs übernimmt die Verantwortung für ein sauberes Aushängen.
  5. Nur zum Ausschalten, wenn ACPI konfiguriert ist, führen Sie möglicherweise Code aus, um den Wechsel in den ACPI- Status S5 vorzubereiten (sanftes Ausschalten).
  6. Auf einem Computer mit mehreren CPUs kann der Code auf einer beliebigen CPU ausgeführt werden, je nachdem, welche den Systemaufruf aufgerufen hat. migrate_to_reboot_cpuachtet darauf, zu einer bestimmten CPU zu wechseln und zu verhindern, dass der Scheduler Code auf anderen CPUs verteilt. Danach läuft nur noch eine CPU.
  7. syscore_shutdownruft die shutdownMethode der registrierten Syscore-Operationen auf . Ich denke, es geht hauptsächlich darum, Interrupts zu deaktivieren. wenige haken haben eine shutdownmethode.
  8. Protokollieren Sie eine Informationsnachricht - das Lied des Schwans.
  9. Schließlich geht durch den Aufruf in irgendeiner maschinenabhängige Art und Weise zur Ruhe machine_restart, machine_haltoder machine_power_off.

Der Ruhezustand- Code durchläuft die folgenden Schritte:

  1. Iterieren Sie durch die Energieverwaltungs-Hooks .
  2. Dateisysteme synchronisieren.
  3. Den gesamten Benutzercode einfrieren .
  4. Verhindern Sie das Hotplugging des Geräts .
  5. Speichern Sie den Systemstatus im Swap-Bereich.
  6. Wenn alles erfolgreich war, schalten Sie die Hardware in den Ruhezustand . Dabei kann es sich anrufen kernel_restart, kernel_haltoder kernel_power_off, oder einige plattformspezifische Winterschlaf - Methode.

Eine andere Möglichkeit zum Herunterfahren des Systems ist machine_emergency_restart. Dies wird durch den magischen SysRq- SchlüsselB aufgerufen . Die OTaste funktioniert anders: Sie ruft aufkernel_power_off .

Das System kann auch zu einer Panik , dh einem nicht behebbaren Fehler, heruntergefahren werden. Beim Versuch, eine Nachricht zu protokollieren, wird in Panik versetzt. Anschließend wird das System neu gestartet (entweder über einen Hardware-Watchdog oder einen Notfall-Neustart).

Gilles 'SO - hör auf böse zu sein'
quelle
+1 Danke! @Gilles Wenn Sie einen Code implementieren möchten, der den RAM des Computers als letzten Schritt löscht / bereinigt, registrieren Sie eine Syscore-Operation für die syscore_shutdown(dh, dies würde meine andere Frage lösen, unix.stackexchange.com/q/122540/24394 ). . Schritt (1) und Schritt (7) erlauben beide das Registrieren von Dingen, die beim Herunterfahren ausgeführt werden sollen, nicht sicher, was ist, + ich hatte den Eindruck, dass die Ausführungsreihenfolge dieser Rückrufe in (1) und (7) nicht beeinflusst werden kann! Ich werde die Dokumente, die Sie erwähnt haben, aber wenn Sie wissen! Vielen Dank!
humanityANDpeace
Ich bin überrascht, dass diese Frage und Antwort nicht mehr positive Stimmen hat.
2

Dies ist nur eine Teilantwort und ich lade mit Sicherheit eine andere Antwort ein, die erschöpfender und klarer sein könnte.

Der Inhalt dieser Antwort stammt aus der kernel/reboot.cDatei des 3.13-Linux-Kernels (was möglicherweise nicht die erste Vermutung ist, da der Name nicht shutdown.c, sondern reboot.c lautet).

Sowieso dort haben wir im Grunde drei Funktionen, die den Prozess des Herunterfahrens des Systems skizzieren

  • void kernel_halt(void) // was mit einem angehaltenen System endet
  • void kernel_power_off(void) // was mit einem ausgeschalteten System endet
  • void kernel_restart(char *cmd) // was das System beendet, um es noch neu zu starten

Diese Funktionen sind sehr kurz und können daher hier vollständig eingefügt werden. Ihr Code zeigt am besten, welche Schritte auf dem Weg zum Herunterfahren des Kernels unternommen werden. (Die Kommentare stammen von mir und sind möglicherweise nicht zu 100% ideal und korrekt. Prüfen Sie, ob Sie sich sicher sind. Es ist ganz einfach, es zu versuchen.

void kernel_halt(void)

void kernel_halt (void)
{
    // 1. Schritt macht:
    // a) Funktionen aufrufen / Rückruf registriert um beim Neustart / Herunterfahren ausgeführt zu werden
    // b) setze system_sate auf SYSTEM_HALT
    // c) Stoppen Sie die Userspacetool-Interaktion
    // d) Funktion device_shutdown () aufrufen
    kernel_shutdown_prepare (SYSTEM_HALT);

    // 2. Schritt: Ich denke, dies ist meistens eine Notwendigkeit für Multi-CPU-Systeme
    migrate_to_reboot_cpu ();

    // 3. Schritt:
    // syscore_shutdown - Führt alle registrierten Systemkern-Shutdown-Rückrufe aus 
    syscore_shutdown ();

    // 4. Nachrichten
    pr_emerg ("System angehalten \ n");
    kmsg_dump (KMSG_DUMP_HALT);

    // 5. Aufruf eines spezifischen CPU-Halt-Codes
    machine_halt ();
}

Das Ganze wird mit dem sys_rebootSystemaufruf eingeleitet, der nicht nur einen Neustart, sondern auch ein Herunterfahren bewirkt, und der ohnehin nicht direkt mit dem Herunterfahren in Verbindung gebracht werden kann.

Mensch und Frieden
quelle