2.4 Der Kernel und die »initrd«
Beim Laden des Kernels gibt es ein klassisches Henne-Ei-Problem: Der Kernel probiert nämlich zunächst, alle notwendigen Module zu laden, die für den Zugriff auf die Hardware notwendig sind. Das sind insbesondere die Treiber zum Ansprechen der Festplatte und des Dateisystems. Die dafür notwendigen Module liegen aber auf dem noch nicht lesbaren Dateisystem.
Um dieses Dilemma zu lösen, lädt der Bootloader nicht nur den Kernel direkt in den Speicher, sondern auch die Initial Ramdisk (initrd). Die initrd besteht aus einem komprimierten cpio-Archiv und enthält ein absolut minimales Linux mit allen für den Start notwendigen Modulen. Der Kernel benutzt die initrd als root-Filesystem. Sobald alle nötigen Treiber geladen sind, bindet der Kernel das eigentliche root-Filesystem ein und startet den systemd-Prozess.
2.4.1 »initrd« erstellen und modifizieren
Bei der Installation eines Systems wird auch eine Initial Ramdisk (initrd) erstellt, die Treiber enthält, die für den Start des Rechners benötigt werden, bevor die Dateisysteme verfügbar sind. Diese Ramdisk wird bei jedem Kernelupdate neu erstellt und mit neuen Versionen der Treiber versehen.
Wenn Sie allerdings Hardware benutzen, die Treiber benötigt, die nicht im Kernel vorhanden sind, wie beispielsweise besondere RAID-Controller oder Netzwerkkarten, so müssen Sie – wenn Sie Ihr System von den Geräten aus starten wollen – selbst Hand anlegen, wenn das nicht die Installationsroutine des Herstellers für Sie übernimmt. Die verschiedenen Distributionen nutzen unterschiedliche Tools für die Erstellung.
In den folgenden Abschnitten finden Sie die Beschreibungen für die im Buch unterstützten Distributionen, gefolgt von einem Abschnitt über die komplett manuelle Erstellung der Initial Ramdisk.
Debian und Ubuntu
Debian und Ubuntu benutzen mkinitramfs und update-initramfs. Wenn Sie nicht besondere Gründe haben, sollte Sie immer update-initramfs verwenden, da dieses Kommando unter anderem auch mkinitramfs auf Basis der bereits bestehenden Konfiguration aufruft.
Die Erstellung der initrd wird über die Konfigurationsdatei /etc/initramfs-tools/initramfs.conf und weitere Dateien innerhalb des Verzeichnisses /etc/initramfs-tools gesteuert. Aufgrund der vielen Kommentare in den Dateien werden Sie schnell zum Ziel kommen.
Einen besonderen Blick verdient die wichtigste Variable, MODULES. Sie kann verschiedene Werte annehmen, wie folgende Auflistung zeigt:
-
most
Das ist die Standardeinstellung bei Ubuntu und Debian. Damit werden fast alle Dateisystem- und Hardwaretreiber übernommen. Die daraus resultierende sehr große Initial Ramdisk kann dafür aber auch fast jedes System starten. -
dep
Das laufende System wird analysiert, um festzustellen, welche Module wichtig sind. Diese Einstellung verkleinert die Initial Ramdisk auf ein Minimum. -
netboot
Wie der Name es beschreibt, werden mit dieser Einstellung nur Treiber verwendet, die für das Starten über das Netzwerk nötig sind. -
list
Ausschließlich Module aus /etc/initramfs-tools/modules werden zum Bau der Initial Ramdisk verwendet. Dies erlaubt die größtmögliche Kontrolle.
[+] Auch ohne weitere Konfiguration werden die Module aus /etc/initramfs-tools/modules bei den Parametern most, dep und netboot zur Initial Ramdisk hinzugefügt.
[ ! ] Die Konfigurationen in den Dateien unterhalb von /etc/initramfs-tools/conf.d können die Werte aus /etc/initramfs-tools/initramfs.conf überschreiben.
Um eine neue Initial Ramdisk zu erstellen bzw. die bestehende aktualisieren zu lassen, können Sie mit update-initramfs den Neubau starten. Die unten stehenden Parameter helfen bei der Erstellung:
-
update-initramfs -u
Hiermit werden alle vorhandenen Initial Ramdisks aktualisiert. -
update-initramfs -k KERNEL
Dieser Parameter wird benötigt, wenn nur die Initial Ramdisks einer bestimmten Kernelversion aktualisiert werden sollen. -
update-initramfs -c
Dieser Parameter erstellt komplett neue Initial Ramdisks.
Der Name der Initial Ramdisk ergibt sich aus dem Namen des Kernels. Eine vorhandene Ramdisk wird somit bei jedem Aufruf von update-initramfs überschrieben.
Wenn Sie dieses Verhalten nicht wünschen, sollten Sie den Parameter backup_initramfs=yes in der Datei /etc/initramfs-tools/update-initramfs.conf setzen oder manuelle Backups erstellen (siehe Listing 2.12):
root@debian:~# update-initramfs -v -k 3.16.0-4-amd64 -c
update-initramfs: Generating /boot/initrd.img-3.16.0-4-amd64
Copying module directory kernel/drivers/hid
(excluding hid-*ff.ko hid-a4tech.ko hid-cypress.ko hid-dr.ko hid-elecom.ko \
hid-gyration.ko hid-icade.ko hid-kensington.ko hid-kye.ko hid-lcpower.ko \
hid-magicmouse.ko hid-multitouch.ko hid-ntrig.ko hid-petalynx.ko \
hid-picolcd.ko hid-pl.ko hid-ps3remote.ko hid-quanta.ko hid-roccat-ko*.ko \
hid-roccat-pyra.ko hid-saitek.ko hid-sensor-hub.ko hid-sony.ko \
hid-speedlink.ko hid-tivo.ko hid-twinhan.ko hid-uclogic.ko hid-wacom.ko \
hid-waltop.ko hid-wiimote.ko hid-zydacron.ko)
Adding module /lib/modules/3.16.0-4-amd64/kernel/drivers/hid/hid.ko
[…]
Adding library /lib/x86_64-linux-gnu/librt.so.1
Adding module /lib/modules/3.16.0-4-amd64/kernel/drivers/md/dm-mod.ko
/usr/share/initramfs-tools/scripts/local-premount/ORDER ignored: not executable
/usr/share/initramfs-tools/scripts/init-top/ORDER ignored: not executable
/usr/share/initramfs-tools/scripts/init-bottom/ORDER ignored: not executable
Building cpio /boot/initrd.img-3.16.0-4-amd64.new initramfs
Listing 2.12 Neuerstellen einer »initrd«
[ ! ] Wenn der Name der Initial Ramdisk bereits existierte, ist nichts weiter zu tun. Sollten Sie aber einen neuen Namen verwenden, muss im Bootloader der entsprechende Name eingetragen werden, sonst können Sie das System nicht mehr starten.
CentOS und openSUSE
Anders als bei Ubuntu und Debian nutzen CentOS und openSUSE das Skript mkinitrd, um eine Initial Ramdisk zu erstellen. Das Skript ermittelt die Treiber, die aufgenommen werden müssen, und nutzt die Informationen aus /etc/sysconfig/kernel, in der eine Liste von Modulen zu finden ist, die zusätzlich hinzugefügt werden sollen (siehe Listing 2.13):
Creating initrd: /boot/initrd-4.1.27-27-default
Executing: /usr/bin/dracut --logfile /var/log/YaST2/mkinitrd.log \
--force /boot/initrd-4.1.27-27-default 4.1.27-27-default
...
*** Including module: bash ***
*** Including module: warpclock ***
*** Including module: i18n ***
*** Including module: ifcfg ***
*** Including module: btrfs ***
*** Including module: kernel-modules ***
Omitting driver i2o_scsi
*** Including module: resume ***
*** Including module: rootfs-block ***
*** Including module: terminfo ***
*** Including module: udev-rules ***
Skipping udev rule: 91-permissions.rules
Skipping udev rule: 80-drivers-modprobe.rules
*** Including module: haveged ***
*** Including module: systemd ***
*** Including module: usrmount ***
*** Including module: base ***
*** Including module: fs-lib ***
*** Including module: shutdown ***
*** Including module: suse ***
*** Including modules done ***
*** Installing kernel module dependencies and firmware ***
*** Installing kernel module dependencies and firmware done ***
*** Resolving executable dependencies ***
*** Resolving executable dependencies done***
*** Hardlinking files ***
*** Hardlinking files done ***
*** Stripping files ***
*** Stripping files done ***
*** Generating early-microcode cpio image ***
*** Store current command line parameters ***
Stored kernel commandline:
resume=UUID=54c1a2e0-c4d6-4850-b639-7a5af8ef4339
root=UUID=0f4f79aa-7544-44b0-a8b7-d1f1947cd24f \
rootflags=rw,relatime,space_cache,subvolid=257,subvol=/@ rootfstype=btrfs
*** Creating image file ***
*** Creating image file done ***
Some kernel modules could not be included
This is not necessarily an error:
*** Including module: udev-rules ***
Skipping udev rule: 91-permissions.rules
Skipping udev rule: 80-drivers-modprobe.rules
*** Including module: haveged ***
*** Including module: systemd ***
*** Including module: usrmount ***
*** Including module: base ***
*** Including module: fs-lib ***
*** Including module: shutdown ***
*** Including module: suse ***
*** Including modules done ***
*** Installing kernel module dependencies and firmware ***
*** Installing kernel module dependencies and firmware done ***
*** Resolving executable dependencies ***
*** Resolving executable dependencies done***
*** Hardlinking files ***
*** Hardlinking files done ***
*** Stripping files ***
*** Stripping files done ***
*** Generating early-microcode cpio image ***
*** Store current command line parameters ***
Stored kernel commandline:
resume=UUID=54c1a2e0-c4d6-4850-b639-7a5af8ef4339
root=UUID=0f4f79aa-7544-44b0-a8b7-d1f1947cd24f \
rootflags=rw,relatime,space_cache,subvolid=257,subvol=/@ rootfstype=btrfs
*** Creating image file ***
*** Creating image file done ***
Some kernel modules could not be included
This is not necessarily an error:
Listing 2.13 Beispiel »mkinitrd« auf openSUSE
Die Installation des Systems setzt automatisch die Variable INITRD_MODULES. Wenn diese Liste um eigene Einträge ergänzt wird, muss anschließend mkinitrd aufgerufen werden.
Analog zu update-initramfs bei Ubuntu und Debian bietet auch mkinitrd einige Optionen an, die Ihnen helfen, die Initial Ramdisk anzupassen:
-
-k KERNEL
Angabe des Kernels, für den die Initial Ramdisk gebaut werden soll. Ohne Angabe des Parameters wird vmlinuz benutzt. -
-i INITRD
setzt den Namen der Initial Ramdisk. Ohne diese Angabe wird /boot/initrd genommen. -
-m MODULES
nimmt eine Liste von Modulen auf der Kommandozeile, ansonsten wird der Inhalt der Variablen INITRD_MODULES aus /etc/sysconfig/kernel ausgelesen. -
-f FEATURES
setzt Funktionalitäten für den Kernel, abhängig davon werden weitere Module und Skripte eingebunden. Als Beispiel seien hier Software-RAID (Parameter dm) und Logical Volume Manager (Parameter lvm2) genannt.
In Listing 2.14 sehen Sie einen Beispielaufruf von mkinitrd:
opensuse:~ # mkinitrd -k 4.1.27-27-default -i initrdtest -m ext4 \
-f "lvm2 dm block"
Listing 2.14 Beispielaufruf von »mkinitrd«
2.4.2 »initrd« manuell modifizieren
Zusätzlich zu den vorgestellten Methoden, die zugegebenermaßen relativ beschränkt sind, lässt sich die Initial Ramdisk (initrd) auch manuell verändern.
Als Basis für Ihre Arbeiten nehmen Sie sich bitte eine vorhandene initrd und packen diese aus. Listing 2.15 zeigt Ihnen, dass es sich bei der initrd um ein minimales root-Filesystem handelt:
root@debian:~# mkdir /var/tmp/initrd
root@debian:~# cd /var/tmp/initrd/
root@debian:/var/tmp/initrd# gzip -dc /boot/initrd.img-3.16.0-4-amd64 \
| cpio --extract --make-directories
90084 blocks
root@debian:/var/tmp/initrd# ls -l
total 40
drwxr-xr-x 2 root root 4096 Aug 4 15:31 bin
drwxr-xr-x 3 root root 4096 Aug 4 15:31 conf
drwxr-xr-x 5 root root 4096 Aug 4 15:31 etc
-rwxr-xr-x 1 root root 7137 Aug 4 15:31 init
drwxr-xr-x 7 root root 4096 Aug 4 15:31 lib
drwxr-xr-x 2 root root 4096 Aug 4 15:31 lib64
drwxr-xr-x 2 root root 4096 Aug 4 15:31 run
drwxr-xr-x 2 root root 4096 Aug 4 15:31 sbin
drwxr-xr-x 5 root root 4096 Aug 4 15:31 scripts
Listing 2.15 »initrd« entpacken
In dem resultierenden Verzeichnis /var/tmp/initrd können Sie nun Ihre Änderungen einpflegen und danach alles wieder einpacken (siehe Listing 2.16):
root@debian:/var/tmp/initrd# find . \
| cpio --create --format=newc \
| gzip > /boot/initrd.adminbuch
90084 blocks
Listing 2.16 »initrd« einpacken
In der Datei /boot/initrd.adminbuch findet sich nun die initrd, die alle Ihre Änderungen enthält.