1.105.2 – Konfiguration, Erstellung und Installation eines angepaßten Kernels und seiner Module
Prüfungskandidaten sollten in der Lage sein, einen Kernel und ladbare Kernelmodule aus Quellcode anzupassen, zu erzeugen und zu installieren. Dieses Lernziel beinhaltet das Anpassen der aktuellen Kernelkonfiguration, das Erzeugen eines neuen Kernels und das Erzeugen von Kernelmodulen nach Bedarf. Ebenfalls enthalten ist die Installation des neuen Kernels sowie jedweder Module und das Sicherstellen, daß der Bootmanager den neuen Kernel und die dazugehörigen Dateien findet (generell in /boot, siehe Lernziel 1.102.2 für mehr Details über Bootmanager und deren Konfiguration).
Die wichtigsten Dateien, Bezeichnungen und Anwendungen:
* /usr/src/linux/*
* /usr/src/linux/.config
* /lib/modules/kernel-version/*
* /boot/*
* make
* make targets:config, menuconfig, xconfig, oldconfig, modules, install, modules_install, depmod
Eine der wesentlichen Unterschiede von Linux gegenüber praktisch allen anderen Betriebssystemen ist, daß der Quellcode verfügbar ist und es so möglich ist, seinen eigenen Kernel zu compilieren. Einen Kernel, der also genau an die Bedürfnisse des eigenen Rechners angepasst ist und keinen unnötigen Ballast enthält. Seit der Einführung des modularen Kernels gibt es zwar keine wirkliche Notwendigkeit mehr, den Kernel selbst zu erzeugen, es ist jedoch immer noch in manchen Fällen besser, einen eigenen Kernel zu benutzen, anstelle eines Standard-Kernels. Ob es sich nun um besonders sicherheitsrelevante Systeme handelt, oder bestimmte Fähigkeiten eines Standard-Kernels nicht erwünscht sind, jedesmal ist es die Lösung, einen entsprechenden eigenen Kernel zu erzeugen.
Einen eigenen Kernel compilieren
Der Vorgang der Compilierung eines Kernels ist kein Kunststück, es werden keine C-Kenntnisse benötigt. Ähnlich wie beim Übersetzen von Paketen, die im Quellcode vorliegen (siehe Abschnitt 1.102.3 der LPI101 Vorbereitung) wird wieder das Programm make benötigt, das anhand eines Makefiles den Kernel erstellt. Im Gegensatz zu einem „normalen“ Programm ist aber etwas mehr Konfigurationsarbeit nötig, bevor der Übersetzungsvorgang gestartet werden kann.
Ein Kernel besteht aus vielen hundert Quellcode-Dateien (*.c), die alle für bestimmte Fähigkeiten des Kernels stehen. Die wesentliche Arbeit bei der Neuerstellung eines Kernels ist es, festzulegen, welche dieser Fähigkeiten erwünscht sind, welche als Modul erstellt werden sollen und welche weggelassen werden sollen. Diese Aufgabe alleine wäre nahezu unlösbar, wenn es dafür keine speziellen Hilfsprogramme gäbe. Aber diese Hilfsprogramme existieren. Sie sind Teil des Kernel-Quellcodes selbst und werden auch über das Makefile (also mit dem Programm make) aufgerufen.
Konfiguration des Kernels
Die Quellen des Kernels werden in ein Verzeichnis unter /usr/src entpackt. Die Kernelversion, die compiliert werden soll, muß unter /usr/src/linux zu finden sein. Am einfachsten wird das über einen symbolischen Link erreicht. /usr/src/linux ist also ein Symlink auf das Verzeichnis, in dem wirklich die Kernelquellen liegen. Innerhalb dieses Verzeichnisses wird alle Konfigurations- und Übersetzungsarbeit geleistet.
Um jetzt den Konfigurationsvorgang zu starten, gibt es drei unterschiedliche Möglichkeiten:
* make config
Startet ein sehr einfaches textorientiertes Programm, das der Reihe nach alle Einstellungen des Kernels abarbeitet und den Anwender auffordert zu entscheiden, ob das jeweilige Feature integriert, als Modul erzeugt oder weggelassen werden soll. Diese Methode ist sehr umständlich, weil immer alle Fragen von vorne bis hinten bearbeitet werden müssen. (Screenshot)
pic
* make menuconfig
Startet ein dialog-basiertes textorientiertes Programm, das auch die Beantwortung aller Fragen ermöglicht. Im Gegensatz zu make config erlaubt es aber das Navigieren durch alle Fragen, Wiederholung von bereits beantworteten Fragen oder nur die Veränderung einzelner Punkte. (Screenshot)
pic
* make xconfig
Ein Tcl/tk basiertes graphisches Programm, das es wie make menuconfig erlaubt, durch die verschiedenen Fragen zu navigieren, nur eben als graphische Anwendung unter X11. (Screenshot)
pic
Alle drei Programme tun im Prinzip das selbe. Sie ermöglichen es dem Anwender, bestimmte Fragen über die Kernelkonfiguration zu beantworten und speichern das Ergebnis in die Datei /usr/src/linux/.config
Diese Datei enthält die Ergebnisse der Konfiguration, also die Antworten auf alle Fragen, die während der Konfiguration beantwortet wurden. Die Form entspricht einer Shellvariablendefinition, also beispielsweise
#
# Automatically generated make config: don’t edit
#
CONFIG_X86=y
CONFIG_ISA=y
# CONFIG_SBUS is not set
CONFIG_UID16=y
#
# Code maturity level options
#
CONFIG_EXPERIMENTAL=y
#
# Loadable module support
#
CONFIG_MODULES=y
# CONFIG_MODVERSIONS is not set
CONFIG_KMOD=y
…
Die Datei /usr/src/linux/.config ist also die Datei, die die gesamte Kernelkonfiguration enthält. Es ist also möglich, verschiedene Konfigurationen herzustellen, indem einfach diese Datei umbenannt wird, um so für verschiedene Rechner jeweils einen Kernel anzupassen.
Die Beantwortung der Fragen während der Kernelkonfiguration ist ein langwieriger Prozess, bei der Version 2.4.18 sind es beispielsweise 656 Stück. Diese Fragen können hier nicht einzeln durchgesprochen werden. Viele Distributionen legen aber bereits eine .config Datei ihres speziellen Kernels bei, die dann benutzt werden kann, um einzelne Veränderungen zu machen.
Die Datei .config ist also auch die Datei, aus der die Voreinstellungen der Fragen entnommen werden. Schematisch können wir das also folgendermaßen darstellen:
pic
Die drei verschiedenen Konfigurationsprogramme bekommen ihre Voreinstellung aus .config und schreiben die veränderten Ergebnisse wieder nach .config.
Normalerweise bringt der Wechsel von einer Kernelversion auf eine andere natürlich auch eine neue .config Datei mit. In der Regel gibt es ja in neueren Versionen auch neuere Einstellmöglichkeiten und damit neue Fragen und Antworten. Um eine bestehende .config Datei auch in einem neuen Kernel zu benutzen, kann der Befehl
* make oldconfig
Benutzt eine alte Konfigurationsdatei und stellt nur die Fragen, die dort noch nicht beantwortet wurden weil es sie noch nicht gab.
benutzt werden. Diese Form bedingt natürlich, daß zunächst die alte .config Datei in das neue Kernelverzeichnis kopiert wurde.
Übersetzung des Kernels
Nachdem jetzt eingestellt ist, welche Teile des Kernels fest eingebaut werden sollen, welche als Modul erstellt werden sollen und welche einfach weggelassen werden sollen, muß der Kernel anhand dieser festgestellten Regeln compiliert werden. Dieser Vorgang läuft in drei Schritten ab, die alle wieder über das Programm make abgewickelt werden.
Der erste Schritt ist nur bei der ersten Kernelcompilation notwendig, bei späteren Übersetzungen kann er weggelassen werden. Es ist allerdings kein Schaden, wenn er auch dann ausgeführt wird. Es geht um die Erstellung der Abhängigkeitsinformationen (dependancies). Der Befehl lautet
* make dep
Erstellt die Abhängigkeitsinformationen, welche .c Datei welche andere benötigt.
Der zweite Schritt ist die Übersetzung des Kernels selbst. Je nach gewünschtem Kernel werden hier verschiedene Befehle benutzt.
* make zImage
Die alte Anweisung, die den Kernel komprimiert in einer Datei ablegt. Bei Intel-basierten Systemen liegt der fertige Kernel dann unter /usr/src/linux/arch/i386/boot/zImage.
* make zdisk
Compiliert den Kernel und kopiert ihn auf eine Diskette, die so zur Bootdisk wird. Auch das die alte Methode.
* make bzImage
Die moderne Methode, einen großen (b wie big) Kernel herzustellen und komprimiert abzulegen. Bei Intel-basierten Systemen liegt der fertige Kernel dann unter /usr/src/linux/arch/i386/boot/bzImage
* make bzdisk
Die neue Methode, eine Bootdisk mit großem (big) Kernel zu erstellen.
Der Vorgang des Compilierens dauert eine Weile, abhängig vom verwendeten Rechner und dessen Ressourcen. Es werden jetzt alle .c Dateien, die durch die Konfigurationsinformation angewählt wurden, in Objektdateien (.o) compiliert die dann später zum Kernel zusammengefasst (linked) werden.
Als dritter Schritt müssen jetzt noch die Module übersetzt werden, also die Teile des Kernels, die nicht fest eingebunden werden sollen, sondern während der Laufzeit ein- und aushängbar sind. Dazu dient der Befehl
* make modules
Übersetzt die ladbaren Module. Die übersetzten Module bleiben in den Verzeichnissen, in denen ihr Quellcode liegt.
Damit ist der eigentliche Compiliervorgang abgeschlossen. Der Kernel und die Module sind jetzt übersetzt, stehen dem System aber noch nicht zur Verfügung, da sie ja noch unterhalb des Verzeichnisses /usr/src/linux liegen.
Installieren des neuen Kernels und der Module
Damit die übersetzten Module auch dahin kommen, wo sie später erwartet werden (in das Verzeichnis /lib/modules/Kernelversion), wird der Befehl
* make modules_install
Kopiert die Moduldateien in eine Verzeichnisstruktur unterhalb von /lib/modules/Kernelversion.
ausgeführt. Dieser Befehl startet dann auch gleich automatisch das Programm depmod um die notwendigen Modulabhängigkeiten zu analysieren und in der Datei /lib/modules/Kernelversion/modules.dep abzulegen.
Um schließlich auch den Kernel selbst zu benutzen, muß die Datei /usr/src/linux/arch/i386/boot/bzImage, die ja den neuen Kernel enthält, unter beliebigem Namen (etwa bzImage.neu) in das Verzeichnis /boot kopiert werden. Auch die Datei /usr/src/linux/System.map sollte dorthin kopiert werden und zwar als /boot/System.map.Kernelversion. Jetzt kann entsprechend der verwendete Bootmanager konfiguriert werden, damit er den neuen Kernel als Bootoption anbietet.
Bei der Installation eines neuen Kernels ist es immer ratsam, zunächst einmal den alten (funktionierenden) Kernel nicht zu überschreiben. So bleibt die Möglichkeit bestehen, den alten Kernel zu laden, falls der neue nicht erwartungsgemäß funktioniert.