Der Kernel stellt die Schnittstelle zwischen
elementarer Hardware (unterste Ebene = Treiber) und dem System dar. Er regelt
z.B. den Umgang mit dem Dateisystem oder einem CD-ROM-Laufwerk. Kurz gesagt,
er ist der zentrale Teil des Systems, der "Kern". Deshalb bekam er wohl auch
den Namen "Kernel". 
Alles, was nicht im Kernel eingebunden oder einkompiliert ist, kann auch nicht
benutzt werden. Wenn ich eine SCSI-Karte in meinen PC einbaue, kann ich sie nicht
nutzen, wenn mir der Kernel keine Unterstützung in irgendeiner Weise bietet.
Diese Unterstützung kann auf 3 Arten erfolgen:
- fest: Die entsprechenden Treiber sind fest im Kernel eingebunden.
- modular: Die Treiber werden als Module geladen, das heisst, sie werden zur
Laufzeit eingebunden und entfernt. Um dies hat sich der Admin dann selbst zu
kümmern (alles halb so wild!).
- gar nicht: Das Gerät erhält keine/hat keine Unterstützung
und hängt nutzlos im System rum, oder die entspechenden Treiber werden
nicht benötigt.
Auf diese Frage kann ich nur einen Spruch zitieren, der damals im
RedHat5.2 Benutzerhandbuch stand:
"Solange man nicht weiss, warum man einen Kernel updaten/kompilieren
soll, braucht man es nicht zu tun!"
Dieser Meinung schließe ich mich an. Aber für all jene,
die es nicht lassen können oder denken, sie bräuchten ein
Kernelupdate, will ich das Thema kurz ansprechen:
- Man hat neue Hardware gekauft (z.B. eine TV.Karte - so wars bei
mir) die erst von neueren Kernel-Versionen richtig unterstützt
wird.
- Der neue Kernel hat ein Feature, von dem man überzeugt ist,
es zu brauchen (z.B. Advanced-Powermanagement, damit sich der PC nach
dem Herunterfahren automatisch ausschaltet).
- Man will sein System anpassen/tunen/auf Vordermann bringen/schlanker
machen - sprich: alles raus, was man nicht braucht. Standardkernel
haben nämlich die Eigenschaft, auf fast allen Systemen zu laufen
und sind folglich nicht speziell auf Deinen Rechner ausgerichtet und
ziemlich groß. Aber ein angepasster Kernel läuft nur mit
genau dem PC, auf den er abgestimmt ist. Dies ist v.a. dann
problematisch, wenn man mal Hardware tauscht/aufrüstet. Denn
dann muss der Kernel wieder neu angepasst werden.
- Oder man will es einfach mal gemacht haben, um zu wissen, ob's schwer ist bzw., um mehr zu lernen
Zunächst schauen wir, ob alles
vorhanden ist, was wir benötigen. Die Kernelquellen und -Includes
müssen installiert sein.
Die kompletten Kernelquellen finden wir bei ftp.kernel.org im Verzeichnis /pub/linux/kernel/v2.4.
Wir können uns entscheiden, ob wir alle Patches auf die aktuelle Version
oder alle Quellen holen wollen. Bei Patches ist darauf zu achten, dass man
nacheinander alle Versionen von der vorhandenen bis zur aktuellen patchen muss.
Im allgemeinen wird es also weniger Aufwand bedeuten, sich gleich die
Kernelquellen zu holen.
Noch ein Hinweis: Die geraden Versionsnummern (zB. 2.4.x) sind stabile
Kernel. Die ungeraden Versionsnummern (zB. 2.5.x) sind Entwicklerkernel,
die nach der Freigabe dann die nächsthöhere gerade Nummer erhalten.
Wir holen uns also zB. das Paket linux-2.4.0.tar.gz oder linux-2.4.0.tar.bz2
(der Download dauert mit ISDN ca. 45 Minuten bis eine Stunde). Beide haben den
gleichen Inhalt. Nur, das mit bz2 gepackte ist rund 6MB kleiner.
Jetzt entpacken wir den Kernel nach /usr/src/linux/, nachdem wir ggf.
vorhandene Daten in ein Unterverzeichnis ( zB. /usr/src/linux/2.2.6, also
einfach die Versionsnummer zum UnterverzeichnisNamen machen) gesichert haben.
Die Kompilierung kann zwar grundsätzlich in jedem Verzeichnis durchgeführt
werden (dann ggf. einen Link auf /usr/src/linux/ legen), doch etliche meist
hardwarenahe Programme erwarten die Kernelquellen in diesem Verzeichnis. Also
werden wir wohl den oben beschriebenen Weg wählen.
Um den Befehl make auführen zu können, muss im genannten
Verzeichnis auch ein Makefile existieren. Es sollte nach der Installation der
Kernelquellen auch dort vorhanden sein.
Nun können wir uns noch Patches für Features besorgen, die nicht
standardmäßig beim Kernel dabei sind. Hier wäre zB. an eines
der Journaling Filesysteme ReiserFS oder ext3 zu denken.
ReiserFS ist zu finden bei ftp.exinferis.de/reiserfs/.
Die Kernelkompilierung muss im Verzeichnis /usr/src/linux
durchgeführt werden, wir wechseln ins Verzeichnis:
root@sonne> cd /usr/src/linux
Ggf. vorhandene Patches werden nun mit folgendem
Befehl eingespielt:
root@sonne> zcat NameDesPatches.gz | patch -p0
Ein Patch lässt sich auch wieder
rückgängig machen. Wenngleich... es soll nicht verschwiegen
werden, dies wird nicht immer gelingen.
root@sonne> patch -R < NameDesPatches
Man sollte über seine Hardware genauestens Bescheid wissen, also
Chipsatz, Hersteller (v.a. auch des MainBoards!). Es werden aber trotzdem
während der Konfiguration einige Fragen auftauchen. Dann sollte man
sein Englisch auffrischen und die Readmes lesen, die mit dem Kernel kommen.
Das ist wirklich wichtig, weil das alles GENAU drinsteht, genauer als in
diesem Dokument. Man sollte sich hier mindestens die README und
CHANGES zu Gemüte führen.
In der CHANGES steht drin, wie man die Programme, die während
des Kernelbaus zum Einsatz kommen, auf die Version hin überprüft.
Ggf. müssen diese nämlich upgedatet werden. (Dies ist i.a. nicht
auf die leichte Schulter zu nehmen; ich bin hinterher drangesessen und hab
mich gewundert, warum ich keine Module laden kann, um dann feststellen zu
müssen, das ich die neuesten modutils nicht hatte.) Speziell
der gcc ist nachher wichtig, weil mit ihm der Kernel kompiliert wird.
Also erstmal die Programme auf Vordermann bringen, was allerdings weiter
kein Problem ist.
Übrigens: Das gilt auch für die README der externen
Patches
Aus Performancegründen ist es
sehr sinnvoll, den Kernel konform zur Rechnerarchitektur zu erstellen.
Für welche Architektur kompiliert wird, hägnt von den Optionen
ab, die im Makefile eingegeben werden, bzw. davon, was der default ist.
Dabei wird in der Regel das System erkannt, und die entsprechenden
Flags für den Compiler werden gesetzt (-O2, -mpentium etc.).
Das Makefile kann anschließend editiert werden, um dann die
Wunscheinstellungen vorzunehmen.
Weiterhin haben wir auch die Möglichkeit, dem
System durch Setzen der Umgebungsvariable CFLAGS mitteilen, für
welche Architektur wir den Kernel, aber auch Libs und weitere Programme, die
wir selbst kompilieren, erstellen wollen. Hierzu ein Beispiel:
root@sonne> export CFLAGS=-O3 -march=pentium
Der Kernel ist zunächst dem eigenen Bedarf anzupassen.
Das Konfigurieren kann auf der Kommandozeile, im Menü im Textmodus
oder unter X-Window erfolgen. Die Auswahl erfolgt durch Eingabe eines der
drei Befehle:
root@sonne> make config
root@sonne> make menuconfig
root@sonne> make xconfig
Anm.: Für die Konfiguration unter dem X-Window ist es sinnvoll,
das X-Window-System als root zu starten, da sonst zusätzliche Massnahmen
getroffen werden müssen, um Zugriff auf das Display eines anderen Benutzers
zu erhalten.
Bevor wir nun mit der Konfiguration beginnen, sollten wir die bestehende
Konfiguration in /usr/src/linux/[*/].config.old sichern.
Über die Konfiguration selbst kann hier eigentlich nichts gesagt werden.
Es geht ja darum, den Kernel den localen Gegebenheiten anzupassen. Wir sollten
sehr sorgfältig arbeiten und darauf achten, dass wir Zusammenhänge nicht
stören. Es würde zB. nicht genügen, nur das Framebuffer-Device zu
wählen, wir müssen auch schauen, welche Zusatzauswahlen getroffen werden
müssen bzw., was sich gegenseitig ausschließt. Als letzten Schritt der
Konfiguration sollten wir diese in /usr/src/linux/[*/].config sichern. Denn
wenn wir nachher feststellen, dass die Auswahl doch noch nicht ganz richtig war,
können wir diese Konfiguration laden und den Fehler suchen. Wir brauchen
nicht alles noch mal im Detail durchgehen.
Nach der Konfigurierung wird der Kernel nun übersetzt. Soll der Kernel
einfach unter /boot installiert werden, ist im Haupt-Makefile (ca. in Zeile 74)
das Kommentarzeichen zu entfernen vor der Zeile
INSTALL_PATH=/boot
Zur Kompilierung können die notwendigen Befehle gemeinsam eingegeben werden:
root@sonne> make dep clean bzImage | tee kernel.out
Anm.: Zunächst kann versucht werden, mit zImage einen schlanken
Kernel zu bauen. Da dies aber in den meisten Fällen nicht gelingen wird,
wird im Beispiel gleich ein grosser Kernel (big), also bzImage generiert.
Wenn genügend Hauptspeicher (über 100 MB) vorhanden ist, kann
der Kernel mit dem Parameter -j (also make -j) übersetzt werden.
Hierbei wird für jedes zu übersetzende Quellfile ein eigener Compiler
gestartet.
Die Anweisung "| tee kernel.out" gilt für die bash und ist nur
notwendig, wenn der Kompilationsvorgang mitgeschrieben werden soll, in diesem
Beispiel in die Datei kernel.out.
Nach der erfolgreichen Übersetzung ist dann der Kernel im Verzeichnis
/usr/src/linux/arch/i386/boot zu finden oder eben im Verzeichnis
/boot, wenn das Haupt-Makefile (s.o.) entsprechend geändert wurde.
In aller Regel werden Teile des Kernels als ladbare Module konfiguriert
worden sein. Die Module müssen nun übersetzt werden:
root@sonne> make modules
Wer sich die Make-Parameter nicht merken möchte und das Arbeiten mit
make etwas einfacher gestalten will, kann unter
http://linux.as-rsi.de/ unter Download nachschauen. Dort liegt MKLINUX,
ein kleines Script, das den User beim der Kernel-Kompilierung unterstützt.
Um festzustellen, inwieweit die Kernelkompilierung vollständig
verlaufen ist oder ob etwas fehlt, könnt Ihr im Verzeichnis /usr/src/linux
aufrufen:
root@sonne> NUR make
Module können mit Parametern aufgerufen werden; diese werden in
der /etc/modules.conf eingetragen. Näheres würde den Rahmen
diese Dokuments aber etwas sprengen. Nur folgendes: Mit
root@sonne> modprobe modulname
kann das Modul geladen werden,
root@sonne> modprobe -r modulname
entlädt das Modul wieder.
root@sonne> lsmod
listet die geladenen Module auf. Man sollte hier wie gesagt auf die
richtige modutils Version achten. Die modutils beeinhalten
Utilities wie modprobe zu Handhabung von Modulen. Sie sind auch
auf ftp.kernel.org erhältlich.
Nachdem der Kernel übersetzt wurde, müssen wir dafür
sorgen, dass er künftig auch gebootet wird.
Falls LILO als Bootloader verwendet wird, könnt Ihr
den Kernel entsprechend entsprechend der folgenden Anleitung installieren:
- Zunächst den alten Kernel sichern,
- danach erfolgt die Installation.
- Anschließend ist LILO aufzurufen.
- Dann sind noch die kompilierten Module zu installieren.
Arbeitet dazu die folgenden Befehle der Reihe nach ab:
root@sonne> cp /boot/vmlinuz /boot/vmlinuz.old
root@sonne> cp /usr/src/linux/arch/i386/boot /boot/vmlinuz
root@sonne> make modules_install
Um bei Bedarf den alten Kernel booten zu können, wird in der /etc/lilo.conf
zusätzlich ein Label Linux.old eingetragen und der alte Kernel nach
/boot/vmlinuz.old umbenannt. Hier nun ein Beispielaufbau-Auszug aus der
/etc/lilo.conf:
image = /boot/vmlinuz
root = /dev/hda5
label = Linux
image = /boot/vmlinuz.old
root = /dev/hda5
label = Alter Kernel
Nach der Anpassung ist nun LILO aufzurufen:
root@sonne> lilo
Nach dem Anpassen der /etc/lilo.conf kann die Installation des
LILO auch automatisch durchgeführt werden:
root@sonne> cd /usr/src/linux
root@sonne> make bzlilo
Anm.: Auch dieses Beispiel gilt wie bei der Kernelkompilierung für
den Fall, dass ein grosser Kernel (big) generiert wurde. Andernfalls wäre
der Parameter zlilo an make zu übergeben.
Nur als Notanker - den wir aber selbstverständlich nicht brauchen
werden , sei
erwähnt, daas wir mit dem Befehl
root@sonne> make oldconfig
die alte Kernelkonfiguration noch mal frisch erstellen können, um ggf. noch
mal ganz von vorn zu beginnen
Wer sich eine Bootdiskette mit dem
neuen Kernel erstellen möchte, kann dies mit folgendem Befehl
tun:
root@sonne> make bzdisk
Anm.: Auch dieses Beispiel gilt wie bei der Kernelkompilierung
für den Fall, dass ein grosser Kernel (big) generiert wurde.
Andernfalls wäre der Parameter zdisk an make zu übergeben.
Es macht durchaus Sinn, die Objektdateien, die bei der Kernelübersetzung
erzeugt wurden, im System zu belassen. Spätere Kernelkompilierungen laufen dann
deutlich schneller ab. Das Löschen der Objektdateien wird allerdings bei
geringem Plattenplatz sinnvoll sein bzw., wenn später voraussichtlich kein
weiterer Kernel mehr kompiliert werden soll. Das Löschen der Dateien geschieht
folgendermaßen:
root@sonne> make clean
Der Parameter clean kann dem make-Befehl auch bereits bei der
Kernelkompilierung mit übergeben werden. Das wird aber nicht unbedingt zu
empfehlen sein. Denn wenn tatsächlich die Kernelkompilierung nicht gelingen
sollte - was mitunter an einer falsch zusammengestellten Modulauswahl oder
fehlenden installierten Paketen liegen kann - müsste make die Objektdateien
erst wieder erstellen, was natürlich wieder die volle Kompilierungszeit erfordern
würde.
Beim Kernelupdating sind folgende Befehle der Reihe nach abzuarbeiten:
root@sonne> cd /usr/src/linux
root@sonne> make mrproper
root@sonne> make xconfig
root@sonne> make dep clean bzImage bzlilo modules modules_config
root@sonne> reboot
bzImage und bzlilo brauchen nicht beide aufgerufen werden.
bzlilo kompiliert auch den Kernel, installiert diesen dann und ruft
LILO auf.
Aus dem alten Linux-Verzeichnis kann die Datei .config in das neue
Linux-Verzeichnis kopiert werden. Dann braucht Ihr z.B. nicht
root@sonne> make xconfig
aufzurufen, sondern
root@sonne> make oldconfig
Hier bekommt Ihr nur die Änderungen angezeigt, die sich aus den Abweichungen
aus den beiden Kernelversionen ergeben.
Bei der richtigen Sorgfalt und nach dem Studium der gebotenen Hilsmittel
ist es durchaus nicht schwer, einen eigenen maßgeschneiderten Kernel zu
kompilieren. Als totaler Linux-Frischling hatte ich zB. das große Glück
, dass ich dank durch
XFree nicht unterstützter Grafikkarte (natürlich eine Hercules
Terminator) X nur über ein Framebuffer Device einrichten konnte. Der eigene
Kernel, den ich mir hierzu bauen musste, war eine prima Einstiegsübung.
Aber wir wollen ja nicht über die Zeiten plaudern, als Linux wirklich noch
schön war (inzwischen ist es leicht geworden). Hier also die Zusammenstellung der wichtigsten Unterlagen,
mit Hilfe derer Euch der Kernelbau gut gelingen sollte:
- Das Distributionshandbuch,
- Die Kernel HOWTO (vieles hab ich aus ihr gelernt und findet sich auch hier wieder),
- Die READMES des Kernels
|