Der Kernel - Konfiguration |
Übersicht |
Wer sich nicht gerade intensiv mit Computern beschäftigt, der wird der Möglichkeit, einen Kernel nach Maß zu generieren, wenig Bedeutung zumessen. Zu komplex mutet die Konfiguration an. Und spätestens nach dem dritten Versuch, der mit einer kryptischen Fehlermeldung endete, landet die Flinte dann im Korn.
Tatsächlich ist es selten notwendig, sich in die Tiefen des Betriebssystems herabzulassen. Die Zeiten, da man durch Entrümpelung den Kernel noch ein paar Maschinenzyklen effizienter trimmte, gehören spätestens seit Athlon und Pentium III der Vergangenheit an. Den Unterschied merken bestenfalls die Benchmark-Programme. Und dort differiert auch nur noch die Zahlenkolonne hinter dem Komma.
Alle (von mir getesteten) Distributoren legen ihren Paketen heutzutage einen stark modularisierten Kernel bei. Nahezu jede verfügbare Eigenschaft liegt zumindest als Modul vor und kann bei Bedarf geladen werden.
Das Backen eines eigenen Kerns ist quasi einzig erforderlich, wenn - aus welchen Gründen auch immer - unbedingt die aktuellsten Kernelversionen verwenden werden müssen. Klar, dass die Aktualität der Distributionen nicht mit dem rasanten Erscheinen neuester (Entwickler-) Versionen Schritt halten kann. Wer nicht warten will, muss nun selbst Hand anlegen und aus den Quellen einen einsatzbereiten Kernel formen.
Andererseits macht es wenig Sinn, jede Distributionsversion mitzunehmen. Meist ändern sich an diesen doch nur wenige Teile, die man sich womöglich schon längst aus dem Netz gezogen hat. Um stets auf der Höhe der Zeit zu bleiben, genügt die Aktualisierung des Kernels. Doch der liegt nur als Quellkode vor, womit man um die Generierung nicht umhin kommt...
Wer übrigens den Kernel nicht übers Modem auf die heimische Platte holen möchte, der sollte mal in linuxspezifischen Zeitschriften schmökern. Regelmäßig enthalten diese CDROM mit den neuesten Programmen und Kernelversionen.
Anmerkung: Nachfolgend beziehen wir uns in den Beispielen immer auf das Verzeichnis /usr/src/linux. Wenn Sie die Kernelquellen unter einem anderen Pfad installiert haben, dann funktionieren die folgenen Aufrufe nur in diesem Stammverzeichnis! Die beschriebene Kernelversion ist 2.4.17.
Die Werkzeuge zur Konfiguration |
Der harte Eingriff in die Quellen bleibt den eingefleischten Kernel-Entwicklern vorbehalten. Es sind einfach zu viele Abhängigkeiten zwischen den einzelnen Kodeteilen, als dass Otto Normalverbraucher auch nur den Hauch eine Chance hätte, dort durchzusehen. Glücklicherweise existieren verschiedene Konfigurationshilfen, die menügesteuert etwas Struktur ins Chaos bringen.
Überliefert aus alten Zeiten, steht gar ein textbasiertes Frage-Antwort-Spiel zur Verfügung:
root@sonne> cd /usr/src/linux root@sonne> make config /bin/sh scripts/Configure arch/i386/config.in # # Using defaults found in .config # * * Code maturity level options * Prompt for development and/or incomplete code/drivers (CONFIG_EXPERIMENTAL) [Y/n/?] ... |
Die konfigurierbaren Punkte sind dieselben, wie in den nachstehend vorgestellten Hilfen. Die Konfiguration erfolgt in vorgegebener Reihenfolge. Die nachträgliche Änderung einer einmal getroffenen Auswahl ist nur durch einen erneuten Programmdurchlauf möglich. Eine Option kann aktiviert (Eingabe von [y] bzw. [Y]) oder deaktiviert werden ([n] bzw. [N]). Manche Eigenschaften lassen sich als Modul realisieren. In der Auswahl symbolisiert ein [M] diese Möglichkeit. Hinweise zum Sinn einer Option erhalten Sie durch Eingabe von [?].
Wenn kein X-Server zur Verfügung steht, ist das auf Dialogboxen aufbauende Werkzeug eine komfortable Hilfe zur Bändigung des Kernels:
root@sonne> cd /usr/src/linux root@sonne> make menuconfig rm -f include/asm ( cd include ; ln -sf asm-i386 asm) make -C scripts/lxdialog all make[1]: Wechsel in das Verzeichnis Verzeichnis »/root/linux/scripts/lxdialog« gcc -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer -DLOCALE -I/usr/include/ncurses -DCURSES_LOC="<ncurses.h>" -c -o checklist.o checklist.c ... |
Abbildung 1: 'make menuconfig'
Die Navigation erfolgt mit den Cursortasten. Die Anwahl einer Option geschieht durch Eingabe von [y], die Abwahl mittels [n]. Steht die Möglichkeit der Realisierung als Modul zur Verfügung, so setzt [M] diese Variante. Das Wechseln zwischen den Möglichkeiten kann ebenso durch wiederholtes Drücken von [Space] geschehen.
Unter X steht die bequemste Möglichkeit der Kernelkonfiguration (Tcl/Tk) zur Verfügung:
root@sonne> cd /usr/src/linux root@sonne> make xconfig rm -f include/asm ( cd include ; ln -sf asm-i386 asm) make -C scripts kconfig.tk make[1]: Wechsel in das Verzeichnis Verzeichnis »/root/linux/scripts« cat header.tk >> ./kconfig.tk ./tkparse < ../arch/i386/config.in >> kconfig.tk ... |
Abbildung 2: 'make xconfig' (offizieller Kernel 2.4.17)
Wir beschreiben die wesentlichen Teile der Konfiguration anhand der durch das X-fähige Werkzeug vorgegebenen Reihenfolge.
Die zuletzt vollzogene Kernelkonfiguration wird jeweils in der Datei .config im Kernel-Stammverzeichnis gespeichert. Nach einem Kernelpatch oder der Installation neuer Kernelquellen (vergessen Sie nicht, .config zu sichern) besteht berechtigtes Interesse, den neuen Kernel mit identischen Einstellungen zu konfigurieren. Wenn die Datei .config existiert, kann mit:
root@sonne> cd /usr/src/linux root@sonne> make oldconfig |
die automatische Konfiguration angeschoben und das ganze Prozedere der manuellen Menüpunkteauswahl umgangen werden. Manche Distributionen (bspw. SuSE) speichern die aktuelle Kernelkonfiguration in einer Datei »/boot/vmlinuz.config«. Um dessen Konfiguration für eine Kernel-Neuerzeugung zu verwenden, bringen sie das make-Ziel »cloneconfig« mit. Abgesehen von den unterschiedlichen Dateien mit den Kernelinformationen arbeiten oldconfig und cloneconfig identisch.
Während ein »make clean« nur die Objektdateien entfernt und somit eine spätere Neuübersetzung aller Kernelteile erzwingt, sorgt ein »make mrproper« für ein Rücksetzen der Kernelquellen in den Originalzustand. Im Wesentlichen handelt es sich um das zusätzliche Entfernen der Statusdateien.
Schließlich existiert »make distclean«, das neben »make mrproper« auch noch die Rückstände von Patchvorgängen entsorgt.
Die Optionen - Schritt für Schritt |
Konfiguration zur Laufzeit |
Etliche Parameter des Kernels können per Kommandozeilenoptionen übergeben werden, was allerdings dessen Start mittels eines Bootmanagers bedingt. Ein Kernel, der als Rettungsanker auf einer Diskette untergebracht wird, wird jedoch i.d.R. zum Booten seinen eigenen Startcode, der im Kernelimage zuvorderst steht, verwenden (u.a. weil ein Bootloader selbst wiederum einen Teil des knappen Diskettenplatzes belegen würde). Bei einem solchen Kernel müssen die »wichtigsten« Parameter passen, damit er bspw. das Root-Dateisystem finden und mounten kann.
Konkret lassen sich folgende Parameter fest in das Kernelimage einbrennen:
Möglich wird das Modifizieren dieser Einträge, weil jene jedes Kernelimage an exakt festgelegten Adressen (beginnend bei Offset 504 Bytes) enthält.
Zum Auslesen und Setzen dieser Parameter existieren mehrere Kommandos, wobei rdev (Root Device) in Zusammenhang mit Optionen identisch zu den weiteren Kommandos wirkt:
-r
-R
-v
-s
-h
Es ist also egal, ob Sie bspw. die Lage der Swap-Partition mittels swapdev oder mittels rdev -s einstellen. Wir beschränken uns in den Beispielen auf rdev.
Wird rdev ohne Argumente gerufen, so gibt es einzig die Lage des aktuellen Root-Dateisystems preis. Es befragt hierzu nicht erst den aktiven Kernel, sondern schaut in der Datei /etc/mtab nach:
root@sonne> rdev /dev/hda9 / |
Um weitere Informationen zu gewinnen, ist das zu betrachtende Kernelimage anzugeben:
# Welches Rootdevice ist in /boot/vmlinuz eingetragen? root@sonne> rdev /boot/vmlinuz Root device /dev/sda5 # Welches Rootflag ist in /boot/vmlinuz gesetzt? root@sonne> rdev -R /boot/vmlinuz Root flags 1 |
Liegt der Kernel auf einer Diskette, so ist er über das entsprechende Device erreichbar (das gilt nur, wenn der Kernel per dd auf das Medium kopiert wurde, was der übliche Weg ist, eine bootbare Diskette zu erzeugen):
# Kernel liegt auf Diskette /dev/fd0: root@sonne> rdev -v /dev/fd0 Video mode 65535 |
Um das Rootdevice permanent im Kernelimage zu ändern, ist das neu zu verwendende Device dem Imagenamen nachzustellen:
root@sonne> rdev /boot/vmlinuz Root device /dev/sda5 root@sonne> rdev /boot/vmlinuz /dev/hda2 root@sonne> rdev /boot/vmlinuz Root device /dev/hda2 |
Die wenigsten Leser werden mit Ram-Disk tatsächlich in Berührung kommen. Dennoch soll auch diese Thematik angesprochen werden. Eine Ram-Disk verwenden i.d.R. die Distributoren, um die Installationskernel einerseits relativ klein und andererseits umfangreich genug zu halten, um auf jeder Standard-Hardware zu booten. Der Kernel enthält nun im Wesentlichen die Fähigkeiten, um eine solche (komprimierte) Ram-Disk zu laden und das enthaltene Skript zu starten. Dieses Skript kümmert sich dann zumeist um die Erkennung der Hardware und die Einbindung der benötigten Treiber. Eine Einführung in die Thematik ist im Abschnitt Booten (Systemadministration) zu finden.
Was muss der Kernel nun wissen? Zum einen muss ihm mitgeteilt werden, dass er überhaupt eine Ramdisk laden soll. Das, was als Kernelargument load_ramdisk veranlasst, regelt intern das Bit Nummer 14 in einem 2 Byte großen Wert (das »Ramdisk-Wort«). Steht es auf "1", lädt der Kernel die Ramdisk; steht es auf "0", ignoriert er sie. Des Weiteren muss die Ramdisk nicht zwangsläufig auf derselben Diskette liegen, wie der Kernel selbst. Daher stoppt eine "1" in Bit 15 des obigen Wertes den Kernel, sodass die Diskette ggf. gewechselt und die Arbeit nach Betätigen von [Enter] fortgesetzt werden kann (entspricht dem Kernelargument prompt_ramdisk). Die ersten 11 Bytes bestimmen nun den Offset (in 1k Blöcken; Kernelargument ramdisk_start), an dem die Ramdisk auf der Diskette liegt (Bit 11-13 werden nicht belegt).
Abbildung 3: Bitbelegung des Ramdisk-Worts
Der korrekte Wert für das Ramdisk-Wort ergibt sich nun aus der Summe von:
Als Beispiel nehmen wir den Fall an, dass Kernel und zugehörige Ramdisk hintereinander auf dieselbe Diskette kopiert werden:
# Kernel kopieren root@sonne> dd if=/boot/kernel_image of=/dev/fd0 bs=1k 324+0 records in 324+0 records out # Ramdisk »hinter« den Kernel kopieren root@sonne> dd if=/boot/initrd of=/dev/fd0 bs=1k skip=324 514+0 records in 514+0 records out |
Die Ramdisk beginnt somit am 325. Block. Damit der Kernel sie auch lädt, muss das Bit 14 gesetzt sein, also ergibt sich der Wert für das Ramdisk-Wort zu 325+214=33093:
root@sonne> rdev -r /dev/fd0 33093 |
Bei heutigen Bildschirmgrößen wirkt die übliche Darstellung mit 80x25-Zeichen etwas unangemessen; etwas »mehr« Text hätte gut und gern auf der Mattscheibe Platz. Um die zu verwendende Auflösung dem Kernel mittzuteilen, ist deren numerische Code zu setzen.
Dabei steht der Wert von -1 für den Standardmodus (also 80x25 Zeichen), eine -2 schaltet den erweiterten VGA-Modus ein (80x50 Zeichen). Die weiteren unterstützen Videomodi werden beginnend bei 1 durchnummeriert; jedoch hängt es von der Grafikkarte ab, welche Modi diese bereit stellt. Aus diesem Grund sollte zunächst -3 gewählt werden, wodurch der Kernel beim Start eine Liste der verfügbaren Modi anzeigt und zur Auswahl auffordert. Entspricht ein Modus Ihren Ansprüchen, können Sie diesen später fest eintragen.
root@sonne> rdev -v /boot/vmlinuz -3 |
Die zulässigen Werte sind "0", um das Rootdevice mit Schreib- und Leseberechtigung zu mounten unt "1", um das Dateisystem schreibgeschützt einzuhängen:
root@sonne> rdev -R /boot/vmlinuz Root flags 1 root@sonne> rdev -R /boot/vmlinuz 0 root@sonne> rdev -R /boot/vmlinuz Root flags 0 |
Diese Option ist nur erforderlich, falls der Hauptspeicher stark begrenzt ist (<16..32MB). Der Kernel wird nun bereits während des Startens das eingetragene Swapgerät aktivieren und den verfügbaren Speicher somit um die Swapgröße erweitern. Gerade in Verbindung mit initialen Ramdisks ist ein Minimum an Hauptspeicher Voraussetzung, damit der Kernel booten kann.
root@sonne> rdev -s /dev/fd0 Swap device is /dev/hda7 root@sonne> rdev -s /dev/fd0 /dev/hda2 root@sonne> rdev -s /dev/fd0 Swap device is /dev/hda2 |