initramfs
initramfs - initial ram filesystem
Beschreibung
Ausgangsdateisystem im Arbeitsspeicher
- Nachfolger von initrd
- initramfs-Archiv
Ein initramfs-Archiv ist eine komprimierte Datei, die für den Systemstart benötigte Dateien enthält
- Es kann vom Linux-Kernel beim Booten als Stammverzeichnis eingehängt werden
- Anschließend wird ein auf dem initramfs vorhandenes Programm (init) gestartet
- Das gestartete Programm kann unterschiedliche Aufgaben erfüllen
- Eingebettetes System
Bei eingebetteten Systemen kann die ganze Funktionalität des Systems im initramfs enthalten sein
- Personal Computer nutzen das initramfs oft nur als einen Zwischenschritt, um Treiber zu laden und andere Vorbereitungen für den Start des eigentlichen Systems zu treffen
- Durch das initramfs bzw
- initrd wurde es möglich, den Bootprozess unter Linux flexibler zu gestalten und Funktionalität aus dem Kernel in den Userspace auszulagern
Bootvorgang
Der Linux-Kernel kann ab Version 2.5.46 von einem initramfs booten
- Das initramfs-Archiv kann im Kernel selbst enthalten sein oder vom Bootloader aus einer Datei in den Arbeitsspeicher geladen werden
- Der Kernel dekomprimiert das initramfs-Archiv und hängt das entpackte Archiv dann als Stammverzeichnis ein
- Als Nächstes wird versucht, das Programm /init aus dem initramfs zu starten
- Schlägt das Starten fehl, versucht der Kernel, das eigentliche root-Volume}} einzuhängen und von dort /sbin/init zu starten
Das initramfs selbst ist ein cpio-Archiv, das meist eine Unix-Shell (oft BusyBox) und andere grundlegende Programme enthält
- In diesem Fall ist /init ein einfaches Shellskript, das die im initramfs enthaltenen Programme auf die gewünschte Weise verknüpft
- Es ist aber auch möglich, dass /init ein C-Programm ist, das gegen eine kleine Variante der libc gelinkt wurde
- Die letzte Aufgabe von /init ist es meist, das eigentliche root-Volume (root device) über das Stammverzeichnis einzuhängen und /sbin/init von dort zu starten
Änderungen gegenüber initrd
- Im Kernel muss kein Dateisystem-Treiber fest einkompiliert sein
- Die Größe des initramfs unterliegt keiner festen Obergrenze
- Zugriffe auf das initramfs werden nicht gepuffert, wodurch Arbeitsspeicher gespart wird
- Verschiedene cpio-Archive können verkettet werden, was das Laden von mehr als einem initramfs-Archiv ermöglicht
Funktion
- Wie initramfs funktioniert
Das grundlegende initramfs ist das Root-Dateisystem-Image, das zum Booten des Kernels verwendet und als komprimiertes cpio-Archiv bereitgestellt wird
Diesem grundlegenden initramfs-Image kann ein unkomprimiertes cpio-Archiv vorangestellt werden, das die sehr früh im Boot-Prozess geladenen Microcode-Daten enthält
Beim Booten führt der Kernel Folgendes aus
- Wenn ein unkomprimiertes cpio-Archiv am Anfang des initramfs vorhanden ist, wird der Mikrocode daraus extrahiert und in die CPU geladen
- Wenn ein unkomprimiertes cpio-Archiv am Anfang des initramfs vorhanden ist, wird dieses übersprungen und der Rest der Datei als grundlegendes initramfs festgelegt
- Andernfalls wird das gesamte initramfs als grundlegendes initramfs behandelt
- Entpacken Sie das Basis-Initramfs, indem Sie es als komprimiertes (gzip standardmäßig auf Debian, LZ4 auf Ubuntu) cpio-Archiv in eine RAM-basierte Festplatte behandeln
- Hängen Sie die RAM-basierte Festplatte ein und verwenden Sie sie als erstes Root-Dateisystem
Ein Großteil des Kernel-Initialisierungs- und Bootstrap-Codes kann dann auf diese Festplatte verschoben und im Benutzermodus ausgeführt werden
- Aufgaben wie das Auffinden der echten Root-Festplatte, die Einrichtung des Netzwerks während des Bootvorgangs, die Handhabung von initrd-ähnlichen RAM-Disks, die ACPI-Einrichtung usw. werden auf diese Weise aus dem Kernel ausgelagert
Ein offensichtlicher Vorteil dieses Schemas ist, dass die Größe des Kernelcodes selbst schrumpfen kann
- Dadurch wird zwar kein Speicher für ein laufendes System freigegeben, da der Linux-Kernel den Initialisierungscode bereits auslagert, wenn er nicht mehr benötigt wird
- Aber eine kleinere Codebasis für den Kernel selbst macht die ganze Sache etwas einfacher zu warten, und das ist immer eine gute Sache
- Die wirklichen Vorteile von initramfs sind jedoch:* Die Anpassung des frühen Boot-Prozesses wird viel einfacher
- Jeder, der Änderungen am Systemstart vornehmen muss, kann dies nun mit User-Space-Code tun; das Patchen des Kernels selbst ist nicht mehr erforderlich
- Durch die Verlagerung des Initialisierungscodes in den User-Space wird das Schreiben dieses Codes einfacher – er verfügt über eine vollständige C-Bibliothek, Speicherschutz usw
- Der User-Space-Code ist erforderlich, um über Systemaufrufe mit dem Kernel zu interagieren
- Durch diese Anforderung wird eine Menge „Magie“ im Kernel, die derzeit vom Initialisierungscode verwendet wird, überflüssig
- Das Ergebnis ist ein sauberer und sicherer Code
Er umfasst
- Eine kleine C-Bibliothek („klibc“) wird zusammengeführt, um Initramfs-Anwendungen zu unterstützen
- Mit klibc wird eine kleine kinit-Anwendung erstellt
- Zu Beginn wird sie nur so viel Arbeit leisten, dass sie zeigt, dass der Mechanismus ordnungsgemäß funktioniert
- Das Initrd-Subsystem (initial ramdisk) wird in kinit und aus dem Kernel selbst verschoben
- Das Mounten des Root-Dateisystems wird in den Benutzerbereich verschoben
- Viel Code für den Umgang mit Dingen wie NFS-gemounteten Root-Dateisystemen wird verschwinden
Der Kernel hat derzeit drei Möglichkeiten, das Root-Dateisystem zu mounten
- Alle erforderlichen Geräte- und Dateisystemtreiber sind in den Kernel kompiliert, keine initrd
- init/main.c:init() ruft prepare_namespace() auf, um das endgültige Root-Dateisystem zu mounten, basierend auf der Option root= und optional init=, um eine andere Init-Binärdatei als die am Ende von init/main.c:init() aufgeführte auszuführen
- einige Geräte- und Dateisystemtreiber, die als Module erstellt und in einer Initrd gespeichert werden
- Die Initrd muss eine Binärdatei „/linuxrc“ enthalten, die diese Treibermodule laden soll
- Es ist auch möglich, das endgültige Root-Dateisystem über linuxrc zu mounten und den Pivot_root-Systemaufruf zu verwenden
- Die Initrd wird über prepare_namespace() gemountet und ausgeführt
- unter Verwendung von initramfs
- Der Aufruf von prepare_namespace() muss übersprungen werden
- Das bedeutet, dass ein Binärprogramm die gesamte Arbeit erledigen muss
- Dieses Binärprogramm kann entweder durch Änderung von usr/gen_init_cpio.c oder über das neue initrd-Format, ein cpio-Archiv, in initramfs gespeichert werden
- Es muss „/init“ heißen
- Dieses Binärprogramm ist dafür verantwortlich, alle Aufgaben von prepare_namespace() zu übernehmen
Um die Abwärtskompatibilität zu gewährleisten, wird die /init-Binärdatei nur ausgeführt, wenn sie über ein initramfs-cpio-Archiv bereitgestellt wird
- Ist dies nicht der Fall, führt init/main.c:init() prepare_namespace() aus, um das endgültige Root-Verzeichnis zu mounten und eine der vordefinierten init-Binärdateien auszuführen
Anhang
Siehe auch
Links
Weblinks