SuSE GmbH

SuSE Support-Datenbank

Titel: Booten mit der initial ramdisk

----------

Übersicht o Stichwortsuche o History o Versionen o Kategorien o Alle Artikel

----------

Booten mit der initial ramdisk

Bezieht sich auf

SuSE Linux: Versionen ab 6.3

Problemstellung:

Sobald der Linux-Kernel geladen ist und das Root-Dateisystem ("/") gemountet hat, können Programme ausgeführt und weitere Kernel-Module geladen werden, um zusätzliche Funktionalitäten bereitzustellen.

Um aber das Root-Dateisystem überhaupt mounten zu können, müssen verschiedene Bedigungen erfüllt sein: Der Kernel benötigt die entsprechenden Treiber, um das Gerät ansprechen zu können, auf dem das Root-Dateisystem liegt (insbesondere SCSI-Treiber). Weiter muss der Kernel den Code enthalten, der benötigt wird, um das Dateisystem lesen zu können (ext2, reiserfs, romfs usw.). Weiterhin ist es denkbar, dass bereits das Root-Dateisystem verschlüsselt ist; zum Mounten ist in diesem Fall die Eingabe des Schlüssels/Passworts erforderlich.

Betrachtet man nur einmal das Problem der SCSI-Treiber, so sind verschiedene Lösungsansätze denkbar: Der Kernel kann alle denkbaren Treiber enthalten. Problematisch, da sich verschiedene Treiber "beissen" können; ausserdem wird der Kernel dadurch sehr gross. Eine andere Möglichkeit besteht darin, verschiedene Kernel zur Verfügung zu stellen, die jeweils nur einen oder sehr wenige SCSI-Treiber enthalten. Auch dieser Weg ist problematisch, da er eine sehr grosse Zahl unterschiedlicher Kernel notwendig macht. Ein Problem, das durch verschieden optimierte Kernel (Pentium-Optimierung, SMP) noch weiter verschärft wird.

Der Ansatz, den SCSI-Treiber als Modul zu laden, führt zur generellen Problematik, der durch das Konzept der initial ramdisk begegnet wird: Das Schaffen einer Möglichkeit, Userspace-Programme bereits vor dem Mounten des Root-Dateisystems ausführen zu können.

Konzept der initial ramdisk

Die initial ramdisk (auch initdisk oder initrd genannt) löst genau diese oben beschriebenen Probleme. Der Linux-Kernel bietet die Möglichkeit, ein (kleines) Dateisystem in eine Ramdisk laden zu lassen, und darin Programme ausführen zu lassen, bevor das eigentliche Root-Dateisystem gemountet wird. Das Laden der initrd wird dabei vom Bootloader (LILO, loadlin usw.) übernommen; all diese Bootloader benötigen lediglich BIOS-Routinen, um Daten vom Bootmedium zu laden. Wenn der Bootloader den Kernel laden kann, dann kann er auch die initial ramdisk laden. Spezielle Treiber sind somit nicht erforderlich.

Ablauf des Bootvorgangs mit initrd

Der Bootloader lädt den Kernel und die initrd in den Speicher und startet den Kernel, wobei der Bootloader dem Kernel mitteilt, dass eine initrd vorhanden ist und wo im Speicher diese liegt.

War die initrd komprimiert (was typischerweise der Fall ist), so dekomprimiert der Kernel die initrd und mountet sie als temporäres Root-Dateisystem. Hierauf wird in der initrd ein Programm mit dem Namen linuxrc gestartet. Dieses Programm kann nun all die Sachen tun, die erforderlich sind, um das richtige Root-Dateisystem mounten zu können. Sobald linuxrc terminiert, wird die (temporäre) initrd wieder unmounted und der Bootvorgang wird wie gewohnt mit dem Mounten des richtigen Root-Dateisystems fortgeführt. Das Mounten der initrd und das Ausführen von linuxrc kann somit als ein kurzes Intermezzo während eines normalen Bootvorgangs betrachtet werden.

Kann die initrd nicht unmountet werden (was i.a. als Fehler angesehen werden sollte), so versucht der Kernel die initrd auf das Verzeichnis /initrd um-zumounten. Ist auch der Mountpunkt /initrd nicht vorhanden, so resultiert eine Fehlermeldung. Das System ist in einem solchen Fall voll funktionsfähig, jedoch kann der durch die initrd belegte Speicher nie freigegeben werden und steht somit nicht mehr zur Verfügung.

linuxrc

Für das Programm linuxrc in der initrd gibt es lediglich die folgenden Anforderungen: Es muss den speziellen Namen linuxrc tragen und es muss im Root-Verzeichnis der initrd liegen. Abgesehen davon muss es lediglich vom Kernel ausgeführt werden können. Das bedeutet, dass linuxrc durchaus dynamisch gelinkt sein darf; in diesem Fall müssen natürlich die shared libraries wie gewohnt vollständig unter /lib in der initrd verfügbar sein. Weiter darf linuxrc auch ein shell script sein; in diesem Fall muss natürlich eine shell in /bin existieren. Kurz gesagt, muss die initrd ein minimales Linux-System enthalten, das die Ausführung des Programmes linuxrc erlaubt. Linuxrc wird mit root-Rechten ausgeführt.

Das echte Root-Dateisystem

Sobald linuxrc terminiert, wird die initrd unmountet und verworfen, der Bootvorgang geht normal weiter und der Kernel mountet das wirkliche Root-Dateisystem. Was als Root-Dateisystem gemountet werden soll, kann durch linuxrc beeinflusst werden. Dazu muss linuxrc lediglich das /proc-Dateisystem mounten und den Wert des echten Root-Dateisystems in numerischer Form nach /proc/sys/kernel/real-root-dev schreiben.

Bootloader

Die meisten Bootloader (vor allem LILO, loadlin und syslinux) können mit initrd umgehen. Die einzelnen Bootloader werden wie folgt angewiesen, eine initrd zu verwenden:

1. LILO

Eintrag der folgenden Zeile in /etc/lilo.conf

initrd=/boot/initrd

Die Datei "/boot/initrd" ist die initial ramdisk. Sie kann (muss aber nicht) komprimiert sein.

2. loadlin.exe

Aufruf mittels:

loadlin  initrd=C:\linux\initrd 

3. syslinux

Eintrag der folgenden Zeile in syslinux.cfg

append initrd=initrd 

Anwendung von initrd bei SuSE

Installation des Systems

Die initrd wird bereits seit geraumer Zeit für die Installation verwendet: Dabei kann der Anwender in linuxrc Module laden und die für eine Installation notwendigen Eingaben (wie vor allem Quellmedium) machen. Linuxrc startet dann YaST, das die Installation durchführt. Hat YaST seine Arbeit getan, teilt es linuxrc mit, wo das Root-Dateisystem des frisch installierten Systems liegt. Linuxrc schreibt diesen Wert nach /proc, beendet sich, und der Kernel bootet in das frisch installierte System weiter.

Bei einer Installation von SuSE Linux bootet man somit von Anfang an quasi das System, das gerade erst installiert wird. Ein echter Reboot nach der Installation erfolgt nur, wenn der gerade laufende Kernel nicht zu den Modulen passt, die im System installiert wurden. Da SuSE Linux derzeit bei der Installation einen Kernel für Uni-Prozessor-Systeme verwendet, geschieht dies derzeit nur dann, wenn im System ein SMP-Kernel mitsamt entsprechenden Modulen installiert wurde. Um alle Module verwenden zu können, muss deshalb der neu im System installierte SMP-Kernel gebootet werden.

Booten des installierten Systems

In der Vergangenheit hat YaST mehr als 40 Kernel für die Installation im System angeboten, wobei sich die Kernel im wesentlichen dadurch unterschieden hatten, dass jeder Kernel einen bestimmten SCSI-Treiber enthielt. Dies war nötig, um nach dem Booten das Root-Dateisystem mounten zu können. Weitere Treiber konnten dann als Modul nachgeladen werden.

Da inzwischen aber auch optimierte Kernel zur Verfügung gestellt werden, ist dieses Konzept nicht mehr tragbar (es wären inzwischen weit über 100 Kernel-Images nötig).

Daher wird nun auch für das normale Starten des Systems eine initrd verwendet. Die Funktionsweise ist analog wie bei einer Installation. Das hier eingesetzte linuxrc ist jedoch einfach nur ein shell script, das lediglich die Aufgabe hat, einige vorgegebene Module zu laden. Typischerweise handelt es sich nur um ein einziges Modul, nämlich denjenigen SCSI-Treiber, der benötigt wird, um auf das Root-Dateisystem zugreifen zu können.

Erstellen einer initrd

Das Erstellen einer initrd erfolgt mittels des Scripts mk_initrd. Die zu ladenden Module werden bei SuSE Linux durch die Variable INITRD_MODULES in /etc/rc.config festgelegt. Nach einer Installation wird diese Variable automatisch durch die richtigen Werte vorbelegt (das Installations-linuxrc weiss ja, welche Module geladen wurden). Dabei ist zu erwähnen, dass die Module in genau der Reihenfolge geladen werden, in der sie in INITRD_MODULES auftauchen. Das ist besonders wichtig, wenn mehrere SCSI-Treiber verwendet werden, da sich ansonsten die Benennung der Platten ändern würde. Strenggenommen würde es reichen, nur denjenigen SCSI-Treiber laden zu lassen, der für den Zugriff auf das Root-Dateisystem benötigt wird. Da das automatische Nachladen zusätzlicher SCSI-Treiber jedoch problematisch ist (wie sollte es getriggert werden, wenn auch am zweiten SCSI-Adapter Platten hängen), laden wir alle bei der Installation verwendeten SCSI-Treiber mittels der initrd.

Das aktuelle mk_initrd prüft, ob für den Zugriff auf das Root-Dateisystem überhaupt ein SCSI-Treiber benötigt wird. Ruft man mk_initrd auf einem System auf, bei dem / auf EIDE-Platten liegt, erstellt es keine initrd, da diese nicht nötig ist, weil die bei SuSE verwendeten Kernel bereits die EIDE-Treiber enthalten. Da inzwischen immer mehr spezielle EIDE-Controller auf den Markt kommen, wird es aber voraussichtlich für die Zukunft nötig werden, auch in diesen Fällen eine initrd für das Booten des installierten Systems zu verwenden.

Wichtig: Da das Laden der initrd durch den Bootloader genauso abläuft wie das Laden des Kernels selbst (LILO vermerkt in seiner map-Datei die Lage der Dateien), muss nach jeder Aenderung der initrd LILO neu installiert werden! Nach einem mk_initrd ist somit immer auch ein lilo nötig!

Fehler und Probleme in SuSE 6.3

Selbstkompilierte Kernel

Uebersetzt man sich selbst einen Kernel, so kann es zu folgendem häufigen Problem kommen: Aus Gewohnheit wird der SCSI-Treiber fest in den Kernel gelinkt, die bestehende initrd bleibt aber unverändert. Beim Booten geschieht nun folgendes: Der Kernel enthält bereits den SCSI-Treiber, die Hardware wird erkannt. Die initrd versucht nun jedoch, den Treiber nochmals als Modul zu laden; dies führt bei einigen SCSI-Treibern (insbesondere beim aic7xxx) zum Stillstand des Systems. Strenggenommen handelt es sich um einen Kernelfehler (ein bereits vorhandener Treiber darf nicht ein zweites Mal als Modul geladen werden können), das Problem ist aber bereits in anderem Zusammenhang bekannt (serieller Treiber).

Es gibt mehrere Lösungen für das Problem: Entweder den Treiber als Modul konfigurieren (dann wird er korrekt in der initrd geladen), oder aber den Eintrag für die initrd aus /etc/lilo.conf entfernen. Aequivalent zur letzteren Lösung ist es, den Treiber aus INITRD_MODULES zu entfernen und mk_initrd aufzurufen, das dann feststellt, dass keine initrd benötigt wird.

Modulparameter

Ist für das Laden eines bestimmten Modules die Angabe von Parametern notwendig, dann gehen diese nach der Installation verloren; sie werden nicht in die für das Booten des Systems verwendete initrd eingetragen. Glücklicherweise gibt es nur sehr wenige SCSI-Treiber, die zwingend die Angabe von Parametern erfordern. Wer auf das Problem stösst, muss sein System mit der Installations-Bootdiskette booten und sich einen Kernel bauen, der den SCSI-Treiber enthält.

Das Problem ist inzwischen behoben, bei SuSE 6.4 werden etwaige Modulparameter auch beim Starten des Systems in der initrd verwendet.

Netzwerktreiber in der initrd

Wurden bei der Installation Netzwerktreiber geladen, so werden auch diese in INITRD_MODULES eingetragen und somit in der initrd beim Booten des Systems geladen. Während dies nicht per se ein Fehler ist, kann es doch in einigen Fällen zu Problemen kommen:

1. NE2000 kompatible Karten: Der Treiber für diese Karten benötigt ein zusätzliches Modul (8390.o). Modul-Abhängigkeiten werden derzeit jedoch nicht beachtet, das Laden des Modules ne.o schlägt somit fehl. Da im späteren Verlauf beim Konfigurieren des Netzwerks das Laden des Netzwerktreibers von kerneld getriggert wird (und diesmal werden durch Verwendung von "modprobe" auch Abhängigkeiten berücksichtigt), handelt es sich um ein rein kosmetisches Problem: Das erste Laden scheitert mit einer Fehlermeldung, das zweite Laden ist jedoch erfolgreich, da das Alias eth0=ne in /etc/modules.conf korrekt gesetzt ist.

2. Erzwingen bestimmter Einstellungen: Soll eine Netzwerkkarte in den full-duplex mode gezwungen werden oder ein bestimmter media type verwendet werden (z.B. beim tulip-Treiber durch den Parameter options=xxx), so schlägt dies fehl, da - wie oben beschrieben - die bei der Installation verwendeten Parameter nicht mehr verwendet werden.

Auch diese Probleme sind mittlerweile gelöst. Zum einen werden künftig Modulparameter korrekt weiterverwendet, zum anderen lässt das Installations-linuxrc nunmehr nur noch SCSI-Treiber in INITRD_MODULES eintragen.

Weitere Informationen

/usr/src/linux/Documentation/ramdisk.txt
/usr/src/linux/Documentation/initrd.txt

----------

Siehe auch:

----------

Stichwörter: BOOT, INITRD, RAMDISK, VFS, SCSI, LILO, LOADLIN

----------

Übersicht o Stichwortsuche o History o Versionen o Kategorien o Alle Artikel

----------

SDB-initrd, Copyright SuSE GmbH, Nuremberg, Germany - Version: 08. Feb 2000
SuSE GmbH - Zuletzt generiert: 08. Feb 2000 13:06:31 by pthomas with sdb_gen 1.00.0