Konfigurieren, Compilieren und Installieren eines Kernels 2.6 unter openSUSE Linux
Autor und Copyright: Dr. Thomas
Hertweck
Ergänzungen und Korrekturen von Jan Engelhardt
Version: 1.01; Stand: 10. Januar 2008
Inhaltsverzeichnis
- Zum Umgang mit diesem Dokument
- Vorwort
- Die Kernel-Quellen
- Auspacken der Kernel-Quellen
- Patchen der Kernel-Quellen
- Klonen einer existierenden Kernelkonfiguration
- Anpassen des Kernel-Releases
- Durchführen der Kernel-Konfiguration
- Compilieren des Kernels
- Installation des Kernels
- Anpassen der Bootloader-Konfigurationsdatei
- Probleme beim Booten des neuen Kernels
- Sonstiges
- Installieren mehrerer Kernel per RPM
- Installieren externer Kernel-Module
- Der Boot-Prozess
- Der Linux-Kernel: wie alles begann
- Links
- Danksagung
- Disclaimer
Zum Umgang mit diesem Dokument
Die neuste Version dieses Dokuments kann stets unter https://www.thomashertweck.de/kernel26.html gefunden werden. Der Einfachheit wegen wird in diesem Howto i.d.R. nur von SUSE, nicht von Novell oder dem openSUSE-Projekt die Rede sein. Dieses Howto ist in keinster Weise direkt mit Novell/SUSE verknüpft, daher sollte Novell/SUSE beim Auftauchen irgendwelcher Probleme mit diesem Howto auch nicht über das Feedback-Formular belästigt werden. Alle Trademarks, die hier erwähnt werden, gehören ihrem jeweiligen Besitzer.
Beim Konfigurieren, Compilieren und Installieren eines neuen Kernels handelt es sich um einen recht komplexen Vorgang. Da teilweise als Root gearbeitet werden muss und da ein falsches Vorgehen dazu führen kann, dass das System sich nicht mehr booten lässt, ist äußerste Sorgfalt bei der Arbeit geboten. Bitte Abschnitte dieses Dokuments immer erst komplett zu Ende lesen, bevor zur Tat geschritten wird. Dieses Dokument bezieht sich primär auf die Installation eines Kernels der 2.6er Serie auf x86-Architekturen. Natürlich können hier nicht alle Eventualitäten berücksichtigt und Situationen erklärt werden, in die man im Laufe der Installation geraten kann; daher bitte erst verstehen, was die einzelnen Befehle bewirken und dann diese ausführen oder entsprechend den eigenen Bedürfnissen anpassen. Der Text ist in einer logischen Reihenfolge aufgebaut und kann daher Schritt für Schritt von vorne her abgearbeitet werden. Zusatzinformationen, weitergehende Erklärungen sowie wichtige Dinge, die es zu beachten gilt, sind in einer Box farbig unterlegt dargestellt und durch entsprechende Icons markiert:
![]() |
Anmerkungen |
![]() |
Erklärungen |
![]() |
Wichtig |
Dateinamen o.ä (insbesondere wenn sie Versionsnummern beinhalten) sind in der Regel als Platzhalter zu verstehen und durch die jeweiligen tatsächlich vorhandenen Dateinamen oder Patches etc. zu ersetzen - dieses Howto kann natürlich nicht bei jeder neuen Kernel-Version angepasst werden. Dieser Text erhebt selbstverständlich keinen Anspruch auf Richtigkeit und Vollständigkeit und es wird keine Gewähr für alle Angaben oder daraus entstehender Konsequenzen übernommen (siehe auch den Disclaimer am Ende des Dokuments).
Vorwort
Es gibt zahlreiche Gründe, die Linux Kernel-Quellen auf seinem System zu installieren, zu konfigurieren und sich einen eigenen Kernel zu compilieren. Eventuell möchte man in die Kernel-Programmierung einsteigen, Zugriff auf die Dokumentation erhalten, die zusammen mit den Kernel-Quellen installiert wird oder man möchte einfach etwas Neues lernen und hat Spaß daran. Es sei angemerkt, dass das Installieren eines neuen Kernels keine triviale Angelegenheit ist. Es ist daher immer eine gute Idee, ein aktuelles Backup sowie eine Notfall-CD zum Booten zur Verfügung zu haben. Hierfür eignet sich neben dem SUSE-Rettungssystem per CD/DVD vor allem auch die Knoppix-CD/DVD, erhältlich unter www.knopper.net/knoppix/.
Dieser Text bezieht sich primär auf die openSUSE-Linux-Distribution sowie auf i386-Architekturen; die hier gegebenen Informationen sollten sich aber auch leicht auf andere Distributionen und andere Architekturen (z.B. x86_64) übertragen lassen.
Dieses Howto soll Neulingen den Einstieg in das korrekte Installieren eines neuen Kernels erleichtern. Experten werden sicherlich hier keine neuen Informationen finden können. Es gibt zahlreiche Literatur zum Linux-Kernel in englischer Sprache, allerdings nur bedingt aktuelle Dokumentation in deutscher Sprache. Da ich immer wieder darauf hingewiesen wurde, wie schwer verständlich manchmal ein englischer Text für jemanden ist, der die englischen Sprache nur bedingt beherrscht, habe ich mich entschlossen, diese Anleitung (neudeutsch: Howto) hier in deutscher Sprache zu verfassen.
Das Howto sollte nicht als Anleitung und schon gar nicht als Aufforderung missverstanden werden, sich ohne große Gedanken mal so eben einen neuen Kernel zu installieren. Manche Kernel brauchen unter Umständen Updates weiterer Pakete (z.B. mkinitrd, module-init-tools, udev, o.ä.), um einwandfrei zu funktionieren. Kernel 2.6 wird stetig weiter entwickelt, es gibt momentan keinen separaten Entwicklerzweig des Kernels. Das bedeutet, dass neuere Versionen nicht immer 100% rückwärtskompatibel sein müssen. Die leider so weit verbreitete Einstellung, stets die neuste Version bei jeder Software haben zu müssen ("Versionitis"), ist beim Kernel sicherlich fehl am Platz! Sicherheitsupdates können bei SUSE-Systemen über YOU (YaST Online Update) eingespielt werden, das gilt auch für den Kernel. Auch KOTD müssen nicht aus den Quellen installiert werden, das entsprechende Verzeichnis auf dem FTP Server oder aus dem Build Service kann als YaST Installationsquelle hinzugefügt werden. Wenn man diesem Howto folgt, sollte man wissen, was man tut, d.h. die Dinge und den Text hier verstehen und sich im Klaren darüber sein, was es bedeutet. Wer unbedacht und ohne Sicherheitsvorkehrungen einen neuen Kernel installiert und es geht dabei etwas schief, darf nicht unbedingt mit Mitleid rechnen.
Ein Wort zu Kernel 2.6: Im Dezember 2003 wurde offiziell Kernel 2.6.0 freigegeben und zum stabilen Kernel deklariert. Die 2.6er Serie, die von Linus Torvalds verwaltet und gepflegt wird, ersetzt die bisherige stabile 2.4er Serie. Mit Kernel 2.6 halten etliche Erweiterungen und Verbesserungen Einzug in die Linux-Welt, sodass es durchaus auch eine 3.0 Version hätte geben können, zumindest war dies eine Zeit lang im Gespräch. Gab es bei der Einführung von Kernel 2.4 etliche Probleme (u.a. wegen Stabilitätsproblemen, dem Austausch des Virtual-Memory-Managements mitten in einer stabilen Serie oder Problemen von ReiserFS mit NFS - letztendlich musste Kernel-Release 2.4.11 sogar offiziell als "don't use" deklariert werden), so wurde bei der 2.6er Serie darauf geachtet, dass die wichtigsten Features bei der offiziellen Freigabe stabil und zuverlässig arbeiten. Hier einige der wichtigsten Änderungen:
- Unterstützung zahlreicher neuer Plattformen.
- Neues und verbessertes System zum Bau des Kernels mit etlichen neuen Features.
- Neuer, wesentlich robusterer ACPI-Code, USB 2.0, IPMI-Treiber, Unterstützung von BIOS-Erweiterungen (z.B. EDD, SBF), u.v.m.
- Neuimplementierung des IDE-Layers (teilweise aus 2.4 übernommen) und Tagged Command Queueing für IDE-Geräte; Wegfall von ide-scsi und nun direkter Zugriff auf CD/DVD-Brenner über das ATAPI-Interface inkl. DMA. Ebenso wurden bedeutende Änderungen am Input-Layer, Block-Layer und Memory-Management-Layer vorgenommen.
- Einführung eines neuen Treibermodells LDM (Linux Device Model).
- Einführung eines neuen Dateisystems sysfs als Schnittstelle zwischen dem Treibermodell LDM und dem User-Space. In Zukunft sollen alle gerätebezogenen Daten aus dem proc-Dateisystem ins sysfs-Dateisystem wandern.
- Neben modprobe kennt der 2.6er Kernel nun auch ein hotplug-Executable.
- Integration von lmsensors sowie die Verbesserung von Suspend-to-Disk und dem dynamischen Heruntertakten von CPUs (Speedstep, PowerNow).
- Wesentliche Verbesserung der Skalierbarkeit und des Reaktionsverhaltens (neuer Scheduler; neuer Block-Device-Layer inkl. I/O-Scheduler und asynchronem I/O; NUMA-Support; Reduzierung von globalen Spinlocks).
- Erweiterung des VM-Subsystems (z.B. Reverse Mapping).
- Der AGP-Code wurde aufgeräumt und es gibt nun Unterstützung für AGP 3.0.
- Der Framebuffer-Layer wurde überarbeitet.
- Schaffung von Echtzeitfähigkeit durch Einführung von Preemption (teilweise schon beim 2.4er Kernel implementiert).
- Übernahme der Native POSIX Thread Library (NPTL) und damit Neugestaltung des Thread-Modells.
- Einbau des XFS-Filesystems und Implementierung eines neuen Quota-Codes im VFS-Layer; POSIX-ACLs; neuer, schnellerer NTFS-Treiber.
- Integration der Advanced Linux Sound Architecture (ALSA).
- Volle IPv6- und IPSec-Unterstützung sowie Unterstützung für das Stream Control Transport Protocol (SCTP).
Das sind nur einige der Änderungen, die sich beim Vergleich von Kerneln der 2.6er Serie mit Kerneln der 2.4er Serie ergeben. Der größte Fortschritt dürften sicherlich die verbesserten Latenz- und Skalierbarkeitseigenschaften sein, die Linux weiter gegenüber kommerziellen Unix-OS aufholen lassen.
Oft tauchen die Fragen auf, wie viel
Festplattenkapazität man braucht, um einen Kernel zu übersetzen
und wie lange das dauert. Hierzu folgende Daumenregeln: das Verzeichnis
mit den Quellen zum SUSE-Kernel 2.6.16 ist nach dem Entpacken ca. 275MB
groß. Beim Compilieren werden viele zusätzliche Dateien
erstellt (Object-Files, Header-Files, usw.), sodass insgesamt wohl pro
installiertem Verzeichnis mit momentan aktuellen Kernel-Quellen mit ca.
400MB benötigtem Festplattenplatz (bei Aktivierung nahezu aller
Kernel-Features) zu rechnen ist. Neuere Kernel benötigen i.d.R. mehr
Festplattenkapazität! Die zum Compilieren des Kernels benötigte
Zeit hängt sehr von der Ausstattung des Rechners - insbes. dem
Prozessor und der Menge an Speicher - ab, aber natürlich auch von
der gewählten Kernel-Konfiguration. So kann es zwischen wenigen
Minuten (aktuelle Rechner mit genügend RAM) bis hin zu vielen
Stunden dauern bei älteren oder ganz alten Rechnern. Zum Glück
ist es aber möglich, einen Kernel für eine ältere Maschine
auch auf einem neuen und damit wohl schnelleren Rechner zu
übersetzen.
Die Kernel-Quellen
Bevor man mit dem Konfigurieren beginnen kann, braucht man natürlich erst einmal die Quellen des gewünschten Kernels. Es gibt mehrere Möglichkeiten, an die Quellen eines bestimmten Kernels zu gelangen:
- openSUSE-DVD bzw. eine entsprechende online-Quelle: dort findet man die Kernel-Quellen des Kernels, der auch bei der Installation im System eingespielt wird. Es ist eine gute Idee, sofern genügend Festplattenkapazität vorhanden ist, die Kernel-Quellen gleich bei der Erstinstallation mitzuinstallieren.
- https://www.kernel.org/ bzw. ein Mirror: hier gibt es die aktuellen (sowie ältere) Linux-Kernelquellen als bzip2- oder gzip-komprimiertes Tar-Archiv. Ebenso sind dort Patches für neue Kernel-Versionen oder Patches für spezielle Kernel erhältlich. Kernel von kernel.org werden oft als Vanilla-Kernel bezeichnet. Vanilla-Kernel sind mittlerweile über den openSUSE Build Service auch im RPM-Format erhältlich (siehe https://download.opensuse.org/repositories/Kernel:/Vanilla/)
Um sich schnell einen Überblick über die
aktuellen Versionen des Vanilla-Kernels zu verschaffen, kann man die
Seite https://www.kernel.org/kdist/finger_banner aufrufen.
- ftp://ftp.suse.com/pub/projects/kernel/kotd/ bzw. ein entsprechender Mirror des SUSE-FTP-Servers, oder https://download.opensuse.org/repositories/Kernel:/HEAD/ des OpenSUSE Build Services: hier findet man die Kernel-Quellen (sowie vorcompilierte Kernel in Form von RPM-Dateien) des neuesten SUSE-Kernels 2.6. Diese Kernel werden nicht offiziell von SUSE unterstützt, sondern zu Testzwecken der Allgemeinheit zur Verfügung gestellt. Diese Kernel werden auch als Kernel-Of-The-Day (KOTD) bezeichnet. Es ist also möglich, dass hier einiges nicht so funktioniert wie erwartet, evtl. sind auch Updates weiterer SUSE-Pakete nötig. In der Regel sind die hier zur Verfügung gestellten Kernel aber relativ stabil. Die KOTD-Testkernel können über YaST installiert werden, wenn das entsprechende Repository als YaST-Installationsquelle hinzugefügt wird.
SUSE- und Vanilla-Kernel-Quellen unterscheiden sich. Zwar
basiert der SUSE-Kernel auf den Vanilla-Kernel-Quellen, jedoch werden
einige SUSE-eigenen Patches angewandt. Sind einige dieser Patches mit
für ein SUSE-System relevanten Features verbunden, so ist es
möglich, dass ein reiner Vanilla-Kernel auf einem SUSE-System nicht
reibungslos läuft.
Zum Download der Kernel-Quellen sollte man stets einen lokalen Mirror verwenden, um die original FTP-Server von kernel.org bzw. suse.com/opensuse.org zu entlasten. Eine Liste von Mirrorn findet man auf den openSUSE Webseiten unter https://de.opensuse.org/Spiegelserver_der_stabilen_Version oder unter https://www.novell.com/de-de/products/linuxprofessional/downloads/ftp/index.html. Eine Liste mit Mirrorn von kernel.org findet sich unter https://www.kernel.org/mirrors/. Des Weiteren spiegeln auch viele der in der SUSE-Liste aufgeführten Server einige Teile von kernel.org.
Verschiedene Kernel Flavors werden alle aus ein
und denselben Quellen erstellt, d.h. es gibt nur ein RPM mit den Quellen
des SUSE-Kernels. Diese Kernel unterscheiden sich nur in ihrer
Konfiguration. Davon weicht momentan allerdings der Realtime-Kernel,
kernel-rt, ab - dieser besitzt aufgrund umfangreicher Patches eigene
Kernelquellen.
Bei den Paketen kernel-source-2.6.xx-y.rpm und
kernel-source-2.6.xx-y.src.rpm handelt es sich um zwei
unterschiedliche Pakete mit unterschiedlicher Zielsetzung. Will
man die Kernel-Quellen installieren, so sollte man das hier zuerst
genannte RPM nehmen. Beim zweitgenannten RPM handelt es sich um ein sog.
Source-RPM. Installiert man dieses Source-RPM, so sucht man vergebens das
Verzeichnis mit den Kernel-Quellen unter /usr/src/! Die
Kernel-Quellen (als Tar-Archiv sowie evtl. Patches) wurden dann
nämlich samt sog. spec-File nach /usr/src/packages/ in die
Unterverzeichnisse SOURCES bzw. SPECS entpackt. So kann
theoretisch das spec-File angepasst, die Kernel-Quellen gepatcht oder ein
neues Source-RPM gebaut werden. Auf dieses Vorgehen soll hier nicht
näher eingegangen werden. Details hierüber findet man im
Handbuch "Maximum RPM" (in englisch) oder in "Das RPM
Buch" (in deutsch).
Es gibt einige Personen, die offiziell Patches für
Vanilla-Kernel zur Verfügung stellen bzw. verwalten. Patches mit dem
Namen "-rc" sind sog. "release candidates", also Vorstufen der
nächsten Kernelversion, die freigegeben wird - dieses Patchset wird
von Linus Torvalds verwaltet. Andrew Mortons Patchset trägt die
Ergänzung "-mm".
Seit Kernel 2.6.11 können Versionsangaben auch
vierstellig sein. Dies wurde bereits einmalig bei Kernel 2.6.8 genutzt,
um schnellstmöglich einen Bug-Fix veröffentlichen zu
können. Die vierstelligen Releases beheben lediglich echte und
bestätigte Fehler und beinhalten keine Neuerungen! Die vierte Zahl
ergänzt die übliche Bezeichnung aus Major-Version ("2"),
Minor-Version ("6") und Patch-Level (z.B. "11").
Auspacken der Kernel-Quellen
Die Quellen des SUSE-Distributionskernels können einfach per YaST2 (oder einer anderen Paketmanagement-Software) installiert werden. Nach der Installation sollte sich unter /usr/src/ ein Verzeichnis mit den SUSE-Kernelquellen befinden. Ebenso wird vermutlich der Link /usr/src/linux auf das neue Verzeichnis mit den Kernel-Quellen zeigen. Falls die Kernel-Quellen nachinstalliert werden und der eigentliche Kernel bereits per YOU gepatcht wurde, so muss nun YOU erneut gestartet werden, um auch die Kernel-Quellen auf die aktuelle Version zu bringen.
Liegen die Kernel-Quellen im RPM-Format als Download vom openSUSE-FTP-Server vor und sollen parallel zu den Quellen des Standard-Distributionskernels installiert werden, so kann nicht einfach das Kommando "rpm -Uhv kernel-source.neu.rpm" benutzt werden, da dieser Befehl die bereits installierten Kernel-Quellen ersetzen würde. Je nachdem, wie das RPM-Paket gebaut wurde, kann es schlicht über den Befehl
$> su $> rpm -ihv /pfad/zu/kernel-source.neu.rpm
installiert werden. Sollte RPM dabei über Konflikte klagen, so kann unter Umständen die RPM-Option "--force" weiterhelfen. Ein
$> su $> rpm -ihv --force /pfad/zu/kernel-source.neu.rpm
sollte die Kernel-Quellen gegebenenfalls korrekt unter /usr/src/ in ein eigenes Verzeichnis installieren. Dies mag eine der wenigen Situationen sein, in denen die genannte RPM-Optionen benutzt werden darf. Generell sollte man von RPM gemeldete Konflikte nicht ignorieren! Mit "rpm -qpl /pfad/zu/kernel-source.neu.rpm" kann zuvor überprüft werden, in welches Verzeichnis sich genau die Kernel-Quellen installieren - so kann gegebenenfalls ein bereits mit gleichem Namen vorhandenes Verzeichnis verschoben bzw. umbenannt werden. Ebenso lässt sich so überprüfen, ob durch das RPM-Paket weitere Dateien außerhalb von /usr/src/ installiert werden. Vermutlich wird wiederum - wie bereits weiter oben erwähnt - der Link /usr/src/linux nach der Installation auf das neue Verzeichnis mit den Kernel-Quellen zeigen.
Liegen die Kernel-Quellen als komprimiertes Tar-Archiv vor (z.B. die Quellen des Vanilla-Kernel), so müssen diese mit dem Programm "tar" entpackt werden. Damit es zu keinen Konflikten kommt, sollte man vorher die Namen bereits vorhandener Kernel-Verzeichnisse unter /usr/src/ (das Verzeichnis, in dem Kernel-Quellen meist installiert werden) prüfen und eventuell (temporär) abändern.
$> su $> cd /usr/src/ $> tar -xvjf /pfad/zu/linux-2.6.23.tar.bz2
bzw.
$> tar -xvzf /pfad/zu/linux-2.6.23.tar.gz
Es bietet sich an, das so entstandene Verzeichnis und alle darin enthaltenen Dateien einem normalen User (und der zugehörigen Gruppe) zu vermachen und den Kernel nicht als Root zu compilieren (das ist auch nicht nötig; lediglich zum Installieren sind Root-Rechte erforderlich). Daher kann ein
$> chown -R myuser linux-2.6.23 $> exit
ausgeführt werden (wir befinden uns weiterhin im Verzeichnis /usr/src). Der Platzhalter "myuser" ist natürlich wie bisher auch entsprechend zu ersetzen, ebenso muss natürlich der korrekte Name für das Verzeichnis mit den Kernel-Quellen angegeben werden. Nutzt man das beim Kernel 2.6 neue Feature des Build-Directory, so kann auf die Änderung des Verzeichniseigentümers verzichtet werden.
Bei Kernel 2.6 ist es möglich, ein sog.
Build-Directory anzugeben. Normalerweise werden die Konfiguration des
Kernels und die beim Compilieren entstehenden Dateien im gleichen
Verzeichnisbaum wie der Kernel-Quellcode abgelegt. Bei Angabe eines
Build-Directory können die Dateien in einem anderen Verzeichnis als
dem Verzeichnis mit den Kernel-Quellen erstellt werden. So kann der
eigentlich Bau des Kernels komplett vom Verzeichnis mit dem Quellcode
getrennt werden, was für wesentlich mehr Flexibilität sorgt.
Dieses Feature ist bei Kerneln der 2.4er Serie nicht enthalten. Die
Benutzung eines Build-Directory wird durch die Angabe von
"O=/pfad/zum/build/directory" beim make-Befehl ermöglicht -
dadurch wird die Variable KBUILD_OUTPUT im Makefile gesetzt und alle zu
erzeugenden Dateien werden fortan umgeleitet. Das Verzeichnis, dessen
Name an make übergeben wird, muss natürlich existieren, sonst
kommt es zu einem Fehler!
Es ist zu beachten, dass bei der Verwendung eines
Build-Directory die Angabe von "O=/pfad/zum/build/directory"
entweder bei jedem (im Folgenden noch näher
erläuterten) make-Befehl benutzt werden muss, oder aber (und das ist
der weitaus praktischere Weg) man wechselt nach dem Klonen oder
Erzeugen einer Konfiguration in das Build-Directory und gibt fortran alle
make-Befehle dort ein!
Als normaler User sollte man dann in das Verzeichnis ./Documentation unterhalb des Verzeichnisses mit den Kernel-Quellen wechseln und sich als Erstes die Datei "Changes" anschauen. In der Datei wiederum ist das Kapitelchen "Current Minimal Requirements" von Interesse: dort steht, welche minimalen Voraussetzungen für den Einsatz des neuen Kernels erfüllt sein müssen. Eventuell müssen einige Software-Pakete erneuert werden, bevor der neue Kernel zum Einsatz kommen kann. Installiert man die zum Standard-Distributionskernel gehörenden Quellen, so kann man sich das Überprüfen der minimalen Systemvoraussetzungen natürlich sparen, denn diese müssen zwangsläufig erfüllt sein. Selbstverständlich müssen bei Bedarf nur Pakete erneuert werden, die auch tatsächlich gebraucht werden: setzt man z.B. kein XFS Filesystem ein, so brauchen die zugehörigen Pakete nicht erneuert oder installiert werden, selbst wenn die "Current Minimal Requirements" dadurch nicht erfüllt werden.
Immer wieder kommt es zu Missverständnissen, was den
Link /usr/src/linux angeht. Prinzipiell muss dieser Link nicht
existieren (Linus Torvalds geht sogar soweit zu sagen, der Link sollte
nicht existieren). Er ist zum Konfigurieren, Compilieren und Installieren
eines neuen Kernels nicht nötig. Existiert dieser Link aber, so
sollte er immer auf die Kernel-Quellen des momentan laufenden Kernels
zeigen. Der Link wird (leider nachwievor) manchmal benutzt, wenn externe
Kernel-Module compiliert werden; oft wertet das entsprechende Makefile
nicht den Link /lib/modules/`uname -r`/build aus (was es
eigentlich tun sollte), sondern vertraut darauf, dass
/usr/src/linux korrekt gesetzt ist. Nur wenn die korrekten
Linux-Header zum Compilieren des Modules eingebunden werden können,
wird es auch zum Kernel passen und sich laden lassen. Sofern also beim
Installieren von neuen Kernel-Quellen der Link /usr/src/linux
existiert und auf ein existierendes Verzeichnis mit (älteren)
Kernel-Quellen, die zum momentan laufenden Kernel passen, zeigt, kann er
zunächst unberührt bleiben. Erst nachdem ein neuern Kernel
compiliert, installiert und erfolgreich gebootet wurde, sollte der Link
/usr/src/linux angepasst werden. Installiert man Kernel-Quellen
per RPM, so wird u.U. der Link automatisch verändert. Hier sollte
man als Anwender ein Auge darauf haben und gegebenenfalls von Hand
einschreiten (oder den Link ganz löschen).
Jede Distribution kommt mit zwei Sets von Kernel-Headern
daher: die "System Kernel Headers" und die "Kernel Source Headers". Die
"System Kernel Headers" sind die Header-Dateien, die vom System wirklich
benutzt werden. Jedes Programm aus dem sog. User-Space (also jedes
Anwendungsprogramm) wird mit Hilfe dieser Header compiliert.
Üblicherweise liegen diese Header-Dateien in
/usr/include/asm und /usr/include/linux. Diese Dateien
sollten nie ersetzt werden, außer bei einem Update der C
Bibliothek (aber das ist selbst für Experten keine einfache Aufgabe
und jedem normalen Anwender kann man vom Updaten der glibc nur abraten).
Diese Header-Dateien können mit vielen unterschiedlichen Kerneln
genutzt werden (es gibt Kompatibilitäts-Code) und sind Teil des
glibc-Paketes. Sie werden normalerweise über das Paket
linux-kernel-headers installiert. Jeder Anwender, der einmal eigene
Programme compilieren will, sollte dieses Development-Paket installiert
haben! Die "Kernel Source Headers" sind Teil der Kernel-Quellen. Diese
Header-Dateien sollten im Quellcode von Anwendungsprogrammen nie
direkt eingebunden werden (es gibt ganz wenige Ausnahmen). Bei
älteren Linux-Distributionen waren /usr/include/linux und
/usr/include/asm nur symbolische Links auf Unterverzeichnisse
innerhalb der Kernel-Quellen in /usr/src/linux und enthielten
somit keinen eigenen Satz von Header-Dateien. Deswegen musste dort der
Link /usr/src/linux zwingend existieren. Eine derartige
Konstellation ist heutzutage nicht mehr anzutreffen. Die "Kernel Source
Headers" werden verwendet, um den Kernel selbst oder Kernel-Module zu
compilieren. Das Makefile zum Compilieren von externen Kernel-Modulen
sollte daher nicht darauf vertrauen, dass der Link
/usr/src/linux existiert und korrekt ist (und damit die
Header-Dateien im Unterverzeichnis ./include der Kernel-Quellen
gefunden werden), sondern stattdessen den Link /lib/modules/`uname
-r`/build auswerten.
Das Verzeichnis mit den Kernel-Quellen muss nicht unter
/usr/src/ liegen, auch wenn es sich in der Vergangenheit so
eingebürgert hat und bei den meisten Distributionen auch wirklich
dort liegt; es kann prinzipiell auch in einem anderen Verzeichnis liegen.
Es ist dann darauf zu achten, dass evtl. vorhandene Links
/usr/src/linux und /lib/modules/`uname -r`/build
korrekt gesetzt sind, sollten die Quellen nach dem Installieren
der Module verschoben werden. Im Zweifelsfalle sollte der Link
/usr/src/linux ganz gelöscht werden!
Patchen der Kernel-Quellen
Unter Umständen ist es nötig, die Kernel-Quellen zu patchen, z.B. wenn man eine Vorversion eines neuen Kernels nutzen oder vorhandene Kernel-Quellen updaten möchte.
Beim Patchen gilt zu beachten: der Patch muss exakt zu den installierten Kernel-Quellen passen, sonst wird es nicht funktionieren oder es ist Handarbeit angesagt. Will man z.B. von den Vanilla-Kernelquellen 2.6.23 zur Version 2.6.24-rc3 aufsteigen, so muss der patch patch-2.6.24-rc3.bz2 (mag evtl. auch mit gzip komprimiert sein, dann trägt der Patch die Endung .gz) auf die Kernel-Quellen 2.6.23 angewendet werden. Patches der Form patch-2.6.x-yy.bz2 werden grundsätzlich auf die aktuelle stabile Version der Kernel-Quellen angewendet. Bei einem Patch patch-2.6.x-rc3.bz2 ist es also nicht nötig, zuerst die -rc1 und -rc2 Patches anzuwenden, sondern der Patch wird direkt auf die Quellen des Kernels 2.6.(x-1) angewendet. Davon zu unterscheiden sind inkrementelle Patches, diese tragen Namen der Form patch-2.6.x-yy-zz.bz2; wie der Name schon andeutet, müsste dieser Patch auf die Quellen des Kernels 2.6.x-yy (das ist bereits ein gepatchter Kernel) angewendet werden und würde diese zu Quellen des Kernels 2.6.x-zz machen. Klingt etwas kompliziert, ist es aber nicht, wenn man sich die Namenskonvention einmal bewusst macht.
Zum eigentlichen Patchen benötigt man das Programm "patch", was sich in einem eigenen RPM auf den CDs bzw. der DVD der Distribution befindet. Da die Patches in der Regel komprimiert sind, sollte man wie folgt vorgehen:
$> cd /usr/src/linux-2.6.x $> gunzip -c /pfad/zu/patch.gz | patch -p1 --dry-run
bzw.
$> bunzip2 -c /pfad/zu/patch.bz2 | patch -p1 --dry-run
je nachdem, ob der Patch mit gzip oder bzip2 komprimiert ist. Die Option "--dry-run" sorgt dafür, dass zunächst keine Dateien verändert werden, sondern lediglich die Anwendung des Patches geprüft wird. Bei einem erfolgreichen Patch-Versuch darf man als Anwender nichts gefragt werden und auf dem Terminal-Fenster dürfen nur die Namen der erfolgreich gepatchten Dateien erscheinen. Wird bereits bei der allerersten zu patchenden Datei gemeldet, dass diese nicht gefunden wird, so ist vermutlich die Option -p1 beim Patch-Befehl falsch. Diese Option gibt an, wie viele / in den Dateinamen, die im Patch-File erwähnt werden, entfernt werden sollen. Das hängt davon ab, wie der Patch erstellt wurde - kommt es also zu o.a. Problem, so sollte man die Option -p anpassen (evtl. -p0 oder auch -p2). Ist der Testversuch schließlich erfolgreich, so kann das eigentliche Patchen durch Entfernen der Option "--dry-run" erfolgen:
$> gunzip -c /pfad/zu/patch.gz | patch -p1
bzw.
$> bunzip2 -c /pfad/zu/patch.bz2 | patch -p1
Passt ein Patch nicht exakt zu den Kernel-Quellen, so kann es vorkommen, dass einige Dateien nicht gepatcht werden können; in solch einem Falle werden Dateien mit der Endung .rej angelegt. Hat man ein bisschen Ahnung, so kann man versuchen, die abgelehnten Patches von Hand durchzuführen, das ist aber wirklich nur für Fortgeschrittene zu empfehlen. Um eine genaue Analyse vorzunehmen, empfiehlt es sich, die Ausgabe des Patch-Befehls mitzuprotokollieren; siehe dazu das Kapitel "Sonstiges".
Nach einem erfolgreichen Patch sollte man den Namen des Verzeichnisses mit den Kernelquellen anpassen. Hat man also z.B. einen Patch patch-2.6.24-rc3 auf die Kernel-Quellen 2.6.23 angewendet, so sollte mit einem
$> su $> cd /usr/src/ $> mv linux-2.6.23 linux-2.6.24-rc3 $> exit
das Verzeichnis korrekt umbenannt werden. Zwingend notwendig ist das natürlich nicht, es dient aber dazu, den Überblick zu behalten. Wie immer ist das hier natürlich nur ein Beispiel und die Namen müssen für die tatsächlichen Gegebenheiten angepasst werden.
Zum Patchen kann auch das Skript ./scripts/patch-kernel im Verzeichnis mit den Kernel-Quellen benutzt werden. Eine kurze Hilfe gibt es durch Eingabe von
$> ./scripts/patch-kernel -h
im Hauptverzeichnis der Kernel-Quellen. Zum Patchen ganz allgemein, siehe auch
$> man patch
aber das versteht sich ja sicher von selbst :-) Meist wird zur Verwaltung von Kernel-Patches heutzutage das Programm "quilt" eingesetzt - siehe Andreas Grünbachers Introduction to Quilt aus dem Jahre 2005 für eine Übersicht.
Ein erfolgreich durchgeführter Patch kann durch die
Option "-R" beim ansonsten identischen Patch-Befehl wie oben
wieder rückgängig gemacht werden! Die Manual-Seite ist für
diese Option leider etwas kryptisch, deswegen sei es hier explizit
erwähnt.
Um auf der sicheren Seite zu sein und mit Sicherheit einen
saubere Kernel-Quellbaum zu haben, kann folgender Befehl ausgeführt
werden - dieser löscht alle generierten Dateien, eine evtl.
vorhandene Konfiguration und zahlreiche evtl. vorhandene Backup-Dateien
und versetzt den Kernel-Quellbaum damit in den Zustand, in dem er
eigentlich sein sollte:
$> cd /usr/src/linux-2.6.x
$> make mrproper
Siehe dazu auch das Kapitel "Sonstiges".
Klonen einer existierenden Kernelkonfiguration
Mitunter ist es nötig, eine bereits existierende Kernelkonfiguration auf neue Kernel-Quellen zu übertragen. Gerade für Anfänger ist es auch hilfreich, mit einer bereits funktionierenden Kernelkonfiguration zu starten und dann für einen eigenen Kernel entsprechende Änderungen an der Konfiguration vorzunehmen. Zum Klonen einer existierenden Konfiguration gibt es mehrere Möglichkeiten. Es hängt u.a. davon ab, ob ein Build-Directory eingesetzt wird oder nicht. Wie bereits angedeutet dient das Build-Directory dazu, die Dateien, die im Laufe der Konfiguration des Kernels und des Compilierens entstehen, vom Verzeichnis mit dem Kernel-Quellcode zu trennen.
- Bei Einsatz eines Build-Directory und vorhandener
/proc/config.gz:
In diesem Falle ist das Klonen der Konfiguration sehr einfach, da die Konfiguration des aktuell laufenden Kernels direkt aus dem proc-Filesystem ausgelesen werden kann:$> cd /usr/src/linux-2.6.x $> zcat /proc/config.gz > /pfad/zum/build/directory/.config $> make O=/pfad/zum/build/directory oldconfig $> make O=/pfad/zum/build/directory modules_prepare
- Bei Einsatz eines Build-Directory und fehlender
/proc/config.gz:
In diesem Falle ist das Klonen der Konfiguration etwas aufwändiger. Es muss von Hand die alte (hoffentlich noch zur Verfügung stehende) .config Datei (oder eine unter anderem Namen gesondert abgespeicherte Konfiguration) in das Build-Directory kopiert werden:$> cd /usr/src/linux-2.6.x $> cp /pfad/zu/alter/.config /pfad/zum/build/directory/.config $> make O=/pfad/zum/build/directory oldconfig $> make O=/pfad/zum/build/directory modules_prepare
Oft werden Kernel-Konfigurationen fü Standard-Kernel einer Distribution auch unter /boot/config-* abgespeichert. - Kein Einsatz eines Build-Directory und vorhandene
/proc/config.gz:
In diesem Falle ist das Klonen der Konfiguration wiederum sehr einfach, da die Konfiguration des aktuell laufenden Kernels direkt aus dem proc-Filesystem ausgelesen werden kann:$> cd /usr/src/linux-2.6.x $> zcat /proc/config.gz > .config $> make oldconfig $> make modules_prepare
- Kein Einsatz eines Build-Directory und fehlende
/proc/config.gz:
In diesem Falle ist das Klonen der Konfiguration wieder etwas aufwändiger. Es muss von Hand die alte (hoffentlich noch zur Verfügung stehende) .config Datei (oder eine unter anderem Namen gesondert abgespeicherte Konfiguration) in das Verzeichnis der Kernel-Quellen kopiert werden:$> cd /usr/src/linux-2.6.x $> cp /pfad/zu/alter/.config .config $> make oldconfig $> make modules_prepare
Gehören die zu konfigurierenden Kernel-Quellen zum momentan laufenden Kernel, so wird man als User nichts gefragt werden. Sind die Kernel-Quellen neuer als der momentan laufende Kernel, so werden vermutlich beim Klonen einige Fragen gestellt werden, ob neue (andere) Features im Kernel aktiviert werden sollen. Diese Fragen müssen entsprechend beantwortet werden.
Bei der Verwendung von openSUSE-Kernel-Quellen und einem
laufenden SUSE-Kernel bzw. der Verwendung von "Kernel .config support"
(d.h., es gibt die Pseudo-Datei /proc/config.gz) kann eine
Konfiguration auch wie folgt geklont werden:
$> cd /usr/src/linux-2.6.x
$> make cloneconfig && make modules_prepare
Dies funktioniert nicht bei Vanilla-Kerneln von kernel.org. Bei Einsatz
eines Build-Directory lautet die Befehlssequenz entsprechend
$> cd /usr/src/linux-2.6.x
$> make O=/pfad/zum/build/directory cloneconfig && \
make O=/pfad/zum/build/directory modules_prepare
Anpassen des Kernel-Releases
Bevor ein eigener Kernel compiliert wird, sollte man dafür sorgen, dass es auf dem System zu keinen Konflikten kommt. Das bedeutet im Prinzip, dass man dem Kernel einen eindeutigen Release-Namen geben sollte, sodass es zu keinen Namenskonflikten mit eventuell bereits auf dem System installierten Kerneln und deren Modulen kommen kann. Es ist kontraproduktiv diesen Schritt durchzuführen, wenn man lediglich eine Konfiguration geklont hat, um z.B. externe Kernel-Module für den laufenden Kernel zu übersetzen. Die hier aufgeführte Problematik tritt wirklich nur auf, wenn man einen eigenen Kernel komplett compilieren und zusätzlich zu einem anderen Kernel im System installieren möchte.
Warum ist das wichtig? Hierzu ein kleines Beispiel: nehmen
wir an, bisher ist im System nur der Kernel 2.6.16-default installiert
(als vmlinuz unter /boot) und die zugehörigen
Module liegen in /lib/modules/2.6.16-default/. Nun möchte
man einen zweiten Kernel erstellen und einige Punkte in der Konfiguration
abändern und diesen neuen Kernel dann zusätzlich zum alten
Kernel im System installieren. Klont man sich eine Konfiguration,
ändert man entsprechend seinen Wünschen die Konfiguration ab
und compiliert und installiert nun diesen Kernel und dessen Module im
System, so hat man ein Problem: für diesen neuen eigenen Kernel
werden die Module wahrscheinlich ins gleiche Verzeichnis unter
/lib/modules installiert werden. Da sich die Konfiguration aber
gegenüber dem alten Kernel geändert hat (evtl. hat man andere
Feature als Modul realisiert oder einige Features fest in den Kernel
compiliert), kommt es zum Konflikt! Ebenso kann es passieren, dass ein
älterer Kernel andere Einträge in der Datei
/etc/modprobe.conf verlangt als ein neuerer Kernel. So gibt es
noch weitere mögliche Konfliktpotenziale. In diesem kleinen
Abschnitt geht es darum, diese Konflikte zu verhindern.
Sowohl bei einem SUSE- als auch bei einem Vanilla-Kernel kann ein eindeutiges Release während der Kernel-Konfiguration vergeben werden (siehe dazu auch den nächsten Abschnitt). Man findet unter dem Punkt "General Setup" die Option "Local version - append to kernel release". Diese Option wird u.U. bereits den Eintrag "-default" tragen, wie es für Standard-SUSE-Kernel üblich ist. Den entsprechenden Eintrag kann man nun erweitern, sodass ein eindeutiges Release entsteht. Die Länge des Eintrags darf 64 Zeichen nicht überschreiten.
Das Kernel-Makefile ist in der Lage, den aktuell konfigurierten Release-Namen auszugeben:
$> cd /pfad/zum/build/directory $> make kernelrelease
Es lässt sich also auf diese Weise leicht die aktuelle Release überprüfen.
Durchführen der Kernel-Konfiguration
Zur Durchführung der Kernel-Konfiguration gibt es mehrere Möglichkeiten; die Konfiguration sollte, wie bereits erwähnt, als normaler User durchgeführt werden. Für eine (fast) automatische Konfiguration stehen folgende Möglichkeiten zur Verfügung (die Eingabe der Befehle erfolgt jeweils im Hauptverzeichnis mit den Kernel-Quellen):
- "make oldconfig" bzw. "make
O=/pfad/zum/build/directory oldconfig"
Diese Möglichkeit, den Kernel zu konfigurieren, wurde bereits vorgestellt: das Klonen (und Ergänzen) einer bereits existierenden (alten) Kernelkonfiguration, siehe Kapitel "Klonen einer existierenden Kernelkonfiguration". - "make defconfig" bzw. "make
O=/pfad/zum/build/directory defconfig"
Bei dieser Art der automatischen Konfiguration wird eine neue Konfigurationsdatei erzeugt, in dem bei allen Kernel-Features die jeweiligen Standardwerte verwendet werden. - "make allmodconfig" bzw. "make
O=/pfad/zum/build/directory allmodconfig"
Bei dieser Art der automatischen Konfiguration wird eine neue Konfigurationsdatei erzeugt, in dem alle Kernel-Features als Modul realisiert werden wo dies möglich ist. - "make allyesconfig" bzw. "make
O=/pfad/zum/build/directory allyesconfig"
Bei dieser Art der automatischen Konfiguration wird eine neue Konfigurationsdatei erzeugt, in dem bei allen Kernel-Features stets mit "Ja" geantwortet wird. - "make allnoconfig" bzw. "make
O=/pfad/zum/build/directory allnoconfig"
Bei dieser Art der automatischen Konfiguration wird eine neue, absolut minimalistische Konfigurationsdatei erzeugt, in dem bei allen Kernel-Features, wo dies möglich ist, stets mit "Nein" geantwortet wird. - "make randconfig" bzw. "make
O=/pfad/zum/build/directory randconfig"
Dies erzeugt mehr oder weniger eine Zufallskonfiguration.
Es ist zu beachten, dass die Konfigurationsmethoden
mittels "defconfig", "allmodconfig", "allyesconfig", "allnoconfig" oder
"randconfig" selten bis nie zu wirklich brauchbaren und für sein
System nutzbaren Konfigurationen führen. Diese Arten, den Kernel zu
konfigurieren, sind nur als Grundlage oder zu Testzwecken gedacht und die
Konfiguration sollte daher mit einer der folgenden Methoden für
seine wahren Bedürfnisse angepasst werden.
- "make menuconfig" bzw. "make
O=/pfad/zum/build/directory menuconfig"
Dadurch wird eine auf ncurses-basierte Eingabemaske gestartet. Um diese Methode der Konfiguration nutzen zu können, müssen die Pakete ncurses und ncurses-devel installiert sein. - "make xconfig" bzw. "make O=/pfad/zum/build/directory
xconfig"
Diese Methode funktioniert nur unter X11 (also im Graphikmodus) und startet eine auf QT-basierte Eingabemaske. Um diese Methode der Konfiguration nutzen zu können, muss eine funktionierende QT Installation (inkl. dem qt-devel Paket) zur Verfügung stehen. - "make gconfig" bzw. "make O=/pfad/zum/build/directory
gconfig"
Diese Methode funktioniert nur unter X11 (also im Graphikmodus) und startet eine auf GTK-basierte Eingabemaske. Um diese Methode der Konfiguration nutzen zu können, muss eine funktionierende GTK+ Installation (inkl. dem pkgconfig Paket) zur Verfügung stehen.
Bei der Konfiguration einzelner Punkte werden entsprechende Hilfetexte angeboten - diese sollte man auf alle Fälle durchlesen, solange man über ein Feature nicht im Klaren ist. Meist stehen dort auch Hinweise, was auszuwählen ist, wenn man diesen Konfigurationspunkt nicht im Detail versteht. Es ist nicht möglich, auf alle Punkte der Kernel-Konfiguration hier einzugehen, weil es a) den Rahmen dieses Textes sprengen würde, b) sich Features ändern oder neue Features dazu kommen und dieser Text daher stets veraltet wäre, und c) jedes Zielsystem anders ist und es schlicht zu viele Hardwarekonfigurationen gibt, um hier allgemeingültige Aussagen zu treffen. Einige wichtige Punkte bei der Kernel-Konfiguration sind jedoch:
- Auswahl des Prozessortyps: es sollte auf alle Fälle der korrekte Prozessortyp ausgewählt werden, denn so kann der Kernel (besser) optimiert werden, was letztendlich auch einen Performance-Vorteil bringt. Eine falsche Auswahl kann übrigens dazu führen, dass der Kernel nicht compiliert oder später nicht bootet.
- Features, die mit Garantie nicht benötigt werden (z.B. Unterstützung für Video4Linux, wenn man keine entsprechende Karte im Rechner hat, oder Firewire (IEEE 1394), wenn man keine entsprechende Schnittstelle hat) sollten deaktiviert werden. Dadurch verringert sich der Compilieraufwand und das Konfliktpotenzial.
- Soll eine Initial Ramdisk zum Einsatz kommen, so ist das entsprechende Feature unter der Rubrik "Block devices" zu aktivieren.
- Für die korrekte Unterstützung von IDE-Festplatten ist der entsprechende Chipsatz auszuwählen unter "ATA/ATAPI/MFM/RLL support", bzw. der entsprechende SCSI-Treiber bei SCSI-Festplatten unter "SCSI device support".
- Es sollten die korrekten Einstellungen zu AGP unter der Rubrik "Character devices" erfolgen. Beim Einsatz der NVIDIA- oder ATI-Grafikkartentreibers sollte der agpgart-Support als Modul realisiert werden, da diese Treiber auch mit einem eigenen AGP-Modul aufwarten können.
- Unter der Rubrik "File systems" sollte die Unterstützung für alle auf dem Rechner vorhandenen Filesysteme (zumindest als Modul) aktiviert werden.
- Man sollte die sog. "Magic SysRq key" Option unter der Rubrik "Kernel hacking" aktivieren. Unter Umständen lässt sich so bei Problemen mit dem Rechner noch ein geregelter Shutdown realisieren. Details zu diesem Feature und die entsprechenden Tastenkombinationen findet man unter ./Documentation/sysrq.txt im Verzeichnis mit den Kernel-Quellen.
Beim Konfigurieren von SUSE-Kerneln sollte wie bereits
erwähnt unter der Rubrik "General Setup" eine gültige und
möglichst eindeutige Angabe für den Eintrag "Local Version"
gemacht werden. Diese Angabe bestimmt das Kernel-Release.
Vor oder beim Verlassen der Konfiguration muss diese abgespeichert werden, sonst gehen alle Einstellungen verloren. Zusätzlich kann man seine eigene Konfiguration in einer weiteren Datei mit beliebigem Namen speichern. Es empfiehlt sich aus Sicherheitsgründen, dies zu tun, denn eine .config Datei ist oftmals schnell überschrieben. Für diese separate Datei (das ist im Prinzip nur eine Kopie der .config aus dem System) sollte man sich einen entsprechend eindeutigen und wiedererkennbaren Namen überlegen. Selbstverständlich kann auch ein einfacher Kopierbefehl an der Kommandozeile ausgeführt werden, um die Datei zu sichern. Man sollte bedenken, dass bei Einsatz eines Build-Directory die Datei .config nicht im Verzeichnis mit den Kernel-Quellen, sondern im angegebenen Build-Directory abgelegt wurde.
Nach dem Konfigurieren der Kernel-Quellen sollte man nun beim Einsatz eines Build-Directory dorthin wechseln. Alle weiteren make-Befehle sind dann im Build-Verzeichnis ohne die Angabe "O=/pfad/zum/build/directory" zu machen. Entsprechend wird im Folgenden die explizite Angabe des Build-Directory bei make-Befehlen nicht mehr erfolgen.
Compilieren des Kernels
Nach der Konfiguration des Kernels kann nun der neue Kernel compiliert werden. Das geschieht genau wie das Konfigurieren selbst als normaler User (nicht als Root). Für den Kernel kann auch direkt ein (rudimentäres) RPM-Paket gebaut werden. Darauf wird später noch etwas näher eingegangen. Ein
$> make
bzw.
$> make all
sollte nun den Kernel erstellen und die Module compilieren. Soll lediglich der Kernel selbst erstellt werden (aber keine Module), so kann der Befehl "make bzImage" (auf i386 Systemen) bzw. generell "make vmlinux" benutzt werden. Die Module selbst werden dann durch Eingabe von "make modules" gebaut. Sofern keine Fehlkonfiguration des Kernels vorliegt oder Bugs im Kernel-Quellcode oder dem benutzten Compiler zu Tage treten, sollte es zu keinen Fehlermeldungen im Laufe der Compilierung oder des Linkens kommen.
Besitzt das System, auf dem man den Kernel compilieren
will, mehrere Prozessoren, so kann man davon Gebrauch machen und die Zeit
zum Compilieren des Kernels verringern. Dazu lässt sich die Option
"-j jobs" von make verwenden, über die man die Anzahl der
parallelen Jobs (Kommandos) angeben kann. So könnte zum Beispiel das
Compilieren des Kernels auch mit
$> make -j4
angestossen werden. Die Verwendung dieser make-Option ist in der Regel
nur auf Mehrprozessorsystemen sinnvoll, allerdings kann ein make
-j2 auch auf Single-Core-Systemen von Vorteil sein.
Was passiert eigentlich genau durch den Befehl "make
bzImage" bzw. "make vmlinux"? Das ist prinzipiell
abhängig von der Architektur; hier sei daher nur auf die x86-Familie
eingegangen. Zunächst werden die C und Assembler Quelldateien
compiliert zu ELF (Executable and Linking Format) Object-Files (.o);
dabei werden einige logisch gruppiert und zu Archiven (.a)
zusammengefasst. Mit Hilfe des Linkers ld werden die
Object-Files und die Archive statisch zu vmlinux gelinkt. Durch
"nm vmlinux" wird die Datei System.map produziert. Im
Verzeichnis ./arch/i386/boot/ wird der Bootsektor Assemblercode
bootsect.S vorprozessiert zu bbootsect.s, dann
verarbeitet und in ein raw binary namens bbootsect umgewandelt.
Danach wird der Setupcode setup.S vorprozessiert zu
bsetup.s und dann wiederum umgewandelt in ein raw binary namens
bsetup. Nach dem Wechsel ins Verzeichnis
./arch/i386/boot/compressed/ wird
<source-Verzeichnis>/vmlinux ins raw binary Format
konvertiert, die ELF Sektionen .note und .comment
entfernt und unter einem temporären Namen gespeichert.
Anschließend wird per "gzip -9" die temporäre Datei
komprimiert und per "ld -r" ins ELF format gebracht und unter
piggy.o gespeichert. Die Kompressionsroutinen head.S
und misc.c werden compiliert zu head.o und
misc.o und dann zusammen mit piggy.o zu
bvmlinux gelinkt. Wiederum wird bvmlinux ins raw binary
Format gebracht (unter Entfernung der ELF Sektionen .note und
.comment) und als bvmlinux.out gespeichert.
Letztendlich werden in ./arch/i386/boot/ mit Hilfe von
./arch/i386/boot/tools/build die Dateien bbootsect,
bsetup und compressed/bvmlinux.out zur Datei
bzImage zusammengefügt.
Das Kernel-Image ist komprimiert. Es sei hier
erwähnt, dass der name "bzImage" nichts mit dem Programm bzip2 zu
tun hat. Der Kernel ist mit dem gzip-Algorithmus komprimiert. Das
"bzImage" steht für "big zImage". Früher, als das Kernel-Image
noch kleiner war, wurde der Kernel üblicherweise mit dem Kommando
"make zImage" erstellt. Der Unterschied zwischen "zImage" und
"bzImage" besteht in einem unterschiedlichen Layout und einem
unterschiedlichen Algorithmus zum Laden des Kernels, wodurch ein Kernel
mit "make bzImage" erstellt eine größere
Kapazität haben kann. Das liegt daran, dass der Linux-Kern hier
direkt in den Speicher jenseits der 1MB-Grenze des Real-Modes geladen
werden kann.
Kommt es beim Compilieren des Kernels zu einem Fehler und
der Vorgang bricht mit "Signal 11" oder einem "Segmentation Fault" ab, so
ist die wahrscheinliche Ursache hierfür ein Hardware-Fehler! Meist
ist es ein defekter Speicherriegel, der Probleme verursacht. Selbst
ausgereifte Speichertestprogramme beanspruchen das RAM selten so wie der
GCC beim Compilieren eines Kernels, man führt quasi gleichzeitig mit
dem Compilieren des Kernels noch ein Hardwaretest durch. Versucht man das
Compilieren nach einem Abbruch erneut mit "make"
anzustoßen und kommt der Vorgang dann ein wenig weiter als vorher,
bricht schließlich aber erneut mit "Signal 11" ab, so handelt es
sich sicher zu 99.9% um einen Hardwarefehler. Bei den hier genannten
Problemen sollte man die Seite https://www.bitwizard.nl/sig11/ aufsuchen.
Möchte man mit seiner erstellten Konfiguration ein Kernel-RPM bauen, so ist das bei Kernel 2.6 sehr leicht möglich; dabei wird auch ein Source-RPM erzeugt. Das Kernel-RPM kann später sehr einfach im System installiert werden, es muss eventuell nur noch eine Initial Ramdisk für den Kernel kreiert und die Bootloader-Konfiguration angepasst werden. Das RPM wird durch Eingabe von
$> make rpm-pkg
bzw.
$> make binrpm-pkg
erstellt (je nachdem, ob auch ein Source-RPM benötigt wird). Statt "make rpm-pkg" kann auch einfach "make rpm" verwendet werden. Je nach Systemkonfiguration sind zum Erstellen des RPMs Root-Rechte erforderlich. Das fertige RPM mit dem compilierten Kernel und dessen Module wird man unter /usr/src/packages/RPMS/ und das Source-RPM in /usr/src/packages/SRPMS/ finden. Baut man ein RPM, so kann man sich das explizite Compilieren des Kernels und der Module (make bzw. make bzImage und make modules) sowie natürlich später die Installation des Kernels von Hand und der Module (make modules_install) sparen. Stattdessen muss das erstellte Binary-RPM installiert werden (Erstellung einer Initial Ramdisk nicht vergessen, falls nötig).
Das fertige Binary-RPM wird (auf 32-bit Linux Systemen)
normalerweise im Verzeichnis /usr/src/packages/RPMS/i386/
landen, unabhängig von eventuell gewählten RPM-Optionen. Das
liegt daran, dass die Architektur des Systems im Kernel als i386
bezeichnet wird, d.h. das Kernel-Makefile ersetzt alle i?86 durch i386.
Dennoch bedeutet dies nicht, dass der Kernel beim Compilieren mit der
Option "-march=i386" übersetzt wird. Das liegt an
arch/i386/Makefile, dem architekturabhängigen Teil des
Kernel-Makefiles, das wiederum anhand der Prozessorwahl der
Kernel-Konfiguration optimale Compilerflags ermittelt. Wird z.B. bei der
Kernel-Konfiguration eine Pentium-M CPU ausgewählt, dann wird beim
Compilieren des Kernels auch "-march=i686" verwendet. Das
Kernel-Makefile ermittelt optimale Compiler-Flags anhand des Zielsystems
selbst, was auch gut so ist. RPM-Optionen wie "--target=i686"
werden ignoriert, weil dies ansonsten zu Konflikten mit dem
gewählten Prozessortyp bei der Kernel-Konfiguration führen
könnte (der neue Kernel wäre damit auf einem Zielsystem evtl.
nicht lauffähig).
Installation des Kernels
Nach dem Compilieren des Kernels und der zugehörigen Module muss der Kernel nun installiert werden. Hier wird davon ausgegangen, dass obige Hinweise zum Anpassen des Kernel-Releases berücksichtigt wurden; ansonsten kann es zu Problemen kommen, insbesondere wenn ein eigens compilierter Kernel mit dem SUSE Standard-Kernel kollidiert und die Module in das gleiche Verzeichnis installieren will. Es sei zudem vorerst davon ausgegangen, dass kein Kernel-RPM erstellt wurde.
Zunächst müssen die Module installiert werden; dieser Schritt (und die folgenden zum Installieren des Kernels im System sowie der Anpassung des Boot-Loaders) ist nur als Root möglich. Wir befinden uns weiterhin im Hauptverzeichnis unserer Kernel-Quellen bzw. in unserem Build-Directory:
$> su $> make modules_install
Durch das Kommando werden die zuvor compilierten Module unter /lib/modules/ installiert, und zwar in ein Verzeichnis, welches den Namen der Variablen UTS_RELEASE aus der Datei ./include/linux/version.h besitzt. Das entspricht auch der Ausgabe, die ein "make kernelrelease" sowie ein "uname -r" nach dem Booten des neuen Kernels liefern würde. Durch das Kommando sollte auch automatisch ein "depmod -ae" zum Aktualisieren der Module-Abhängigkeiten ausgeführt werden.
Nun sollte der neu erstellte Kernel sowie die neue Datei System.map (als Root) nach /boot kopiert werden. Dabei ist zu beachten, dass die kopierten Dateien im Verzeichnis /boot mit der gleichen Endung versehen werden; diese Endung sollte wiederum dem Namen des Verzeichnisses, in das die Module installiert wurden (= Kernel-Release), entsprechen. Gehen wir hier z.B. davon aus, dass wir einen Kernel 2.6.24-th1 erstellt haben, so wurden die Module in das Verzeichnis /lib/modules/2.6.24-th1 installiert und wir sollten nun
$> cp ./arch/i386/boot/bzImage /boot/vmlinuz-2.6.24-th1 $> cp ./System.map /boot/System.map-2.6.24-th1
ausführen. Man beachte, dass zwischen dem Namen der Datei und der Versionsangabe ein Bindestrich hinzukommt.
Hat man für den neuen Kernel ein RPM-Paket erstellt, so müssen bzw. dürfen die Module sowie der Kernel und die Datei System.map nicht von Hand (wie oben angegeben) installiert werden. Stattdessen wäre nun das gebaute Binary-RPM-Paket als Root zu installieren. Da das verwendene spec-File zum Erstellen des Kernel-RPMs sehr einfach gehalten ist, wird eine Initial Ramdisk nicht automatisch generiert durch ein RPM-Postinstall-Script. Eine Initial Ramdisk muss daher von Hand wie unten angegeben erstellt werden. Alternativ kann theoretisch ein Kernel-RPM mit einem angepassten original SUSE-Kernel-Spec-File generiert werden. Dann würden manuell durchzuführende Schritte quasi komplett entfallen. Allerdings ist diese Methode sicherlich nur für fortgeschrittene User mit Kenntnissen zum Bau von RPM-Paketen zu empfehlen.
Die Datei System.map, die über das Programm
"nm" produziert wird, enthält die Namen und Adressen von
Symbolen des Linux Kernels. Sie ist für den Alltag eines
Linux-Systems nicht lebenswichtig. Die Datei System.map wird
prinzipiell zum Debuggen bei Kernel-Problemen gebraucht.
Was ist eigentlich ein Oops? Wer selbst eigene Software
programmiert, der wird einen berühmten Fehler kennen: Signal 11,
auch "Segmentation Fault" genannt. Einen ähnlichen Fehler kann es
natürlich z.B. auch beim Linux-Kernel geben. Dereferenziert der
Linux Kernel z.B. einen ungültigen Pointer, so kann das
schwerwiegende Auswirkungen haben. Ein Oops ist also ein Hinweis auf
einen Kernel-Bug und sollte immer gefixt werden. In anderen Worten: ein
Oops ist die Art des Kernels dem User mitzuteilen, dass etwas
Unangenehmes vorgefallen ist (was genau schief gelaufen ist, lässt
sich nur durch Analyse des Oops sagen). Der Linux Kernel ist aber relativ
robust und - im Gegensatz zu einem Segmentation Fault bei einem eigenen
Programm - muss der Kernel dadurch nicht instabil werden oder gar
abstürzen. Ein Oops hat also nichts mit einem Kernel-Panic zu tun.
Bei einem Kernel-Panic ist der Linux Kernel in einem Zustand, bei dem es
nicht mehr weiter geht - das System muss rebootet werden. Natürlich
kann ein Oops einen Kernel-Panic verursachen, wenn der Fehler in einem
lebenswichtigen Teil des Kernel-Codes auftritt. Tritt der Fehler nur in
einem Gerätetreiber auf, so wird es vermutlich nicht zu einem
Kernel-Panic kommen - der Kernel wird sich lediglich mehr oder weniger
elegant aus dem Kontext zurückziehen und versuchen, die Situation
unter Kontrolle zu bringen. Folge kann auch sein, dass Prozesse
hängenbleiben, weil z.B. eine Resource durch einen Oops in einem
anderen Thread nicht wieder freigegeben wurde. Der Oops wird über
die üblichen Wege meist in /var/log/messages
festgehalten.
Gegebenenfalls ist nun eine Initial Ramdisk für den neuen Kernel zu erstellen (wiederum als Root):
$> cd /boot $> mkinitrd -k vmlinuz-2.6.24-th1 -i initrd-2.6.24-th1
Wie man sieht, sollte auch die Initial Ramdisk mit einer Versionsnummer versehen werden. Die Optionen "-k" und "-i" müssen hier benutzt werden, da sonst die Initial Ramdisk nicht für den neuen, sondern für den momentan noch laufenden Kernel erstellt würde. Die Module, die in die Initial Ramdisk aufgenommen werden, werden der Datei /etc/sysconfig/kernel entnommen (Variable: INITRD_MODULES). Will man andere Module in die Initial Ramdisk aufnehmen, so können deren Namen per Option "-m" bei mkinitrd angegeben werden. Siehe auch "mkinitrd -h" für eine Hilfe zum Programm. Ein Splash-Bildschirms sollte automatisch berücksichtigt werden. Hierbei wird u.a. die Datei /etc/sysconfig/bootsplash ausgewertet. Für Details zu bootsplash (auch zum Einsatz eigener Themes), siehe https://www.bootsplash.org/.
Zum Installieren des Kernels steht auch das Kommando
"make install" zur Verfügung. Aber Vorsicht: dadurch werden
symbolische Links im Verzeichnis /boot verändert, welche
die Standardeinträge in der Bootloader-Konfigurationsdatei betreffen
können. Es kann daher passieren, dass man seinen alten,
funktionierenden Kernel nach einem Reboot zwar noch auswählen kann,
dahinter aber letztendlich doch der neue Kernel steckt und daher der alte
Kernel faktisch nicht mehr gebootet werden kann. Entweder muss man also
im Anschluss an make install die Standardeinträge für
die SUSE-Default-Kernel überprüfen und ggf. anpassen, oder aber
man installiert den Kernel wie hier angegeben von Hand - letzteres halte
ich für die sicherere Methode, da alle Schritte einzeln
durchgeführt und stets überprüft und angepasst werden
können.
Nun muss noch die Konfiguration des Bootloaders angepasst werden, um den neuen Kernel booten zu können. Das wird im folgenden Abschnitt beschrieben.
Anpassen der Bootloader-Konfigurationsdatei
Wird LILO als Bootloader benutzt, so muss die Datei /etc/lilo.conf (als Root) angepasst werden. Die Datei ist um einen Abschnitt für den neuen Kernel zu ergänzen; man kann sich dabei an den bereits existierenden Sektionen in der Datei orientieren. So ein Eintrag könnte in unserem Beispiel wie folgt aussehen:
[...] image = /boot/vmlinuz-2.6.24-th1 label = linux2618 append = "selinux=0 splash=0 resume=/dev/hda7 showopts" initrd = /boot/initrd-2.6.24-th1 optional root = /dev/hda6 [...]
Die entsprechenden Optionen, die hier gesetzt sind, können "man lilo.conf" entnommen werden; sie sind dort ausführlich erklärt. Desweiteren sollte man neben der bereits genannten Lektüre noch "man lilo" und die Dateien unter /usr/share/doc/packages/lilo/ lesen.
Findet sich ein Eintrag "default" in
/etc/lilo.conf, so wird der mit diesem Label spezifizierte
Kernel per default geladen, ansonsten ist es der Kernel des ersten
Eintrags "image" oder "other" (was also u.U. auch ein anderes
Betriebssystem als Linux sein kann). Einen neuen Kernel sollte man
zunächst einmal nicht per default booten, sondern beim Booten im
Menü oder am LILO-Prompt auswählen. Stellt sich heraus, dass
der neue Kernel erfolgreich bootet und eingesetzt werden kann, so kann
die Datei /etc/lilo.conf entsprechend angepasst und der neue
Kernel als Standard gebootet werden.
Nach der Änderung der Datei /etc/lilo.conf ist der Bootloader (als Root) wie üblich neu zu installieren:
$> /sbin/lilo
Dabei werden die Labels aus /etc/lilo.conf gelistet, der Eintrag, der als Standard gebootet wird, ist durch einen * (Stern) gekennzeichnet.
Nun aber zum Bootloader GRUB: Der größte Unterschied zwischen LILO und GRUB besteht darin, dass GRUB seine Konfiguration beim Booten direkt aus /boot selbst lesen kann. GRUB muss daher nach Änderungen an der Konfiguration nicht neu installiert werden. Die Konfigurationsdatei liegt in /boot/grub/ und heißt menu.lst. Hier ein Beispiel wie menu.lst aussehen kann:
default 0 title linux root (hd0,5) kernel /boot/vmlinuz root=/dev/hda6 vga=0x342 resume=/dev/hda7 showopts initrd /boot/initrd title linux2624 root (hd0,5) kernel /boot/vmlinuz-2.6.24-th1 root=/dev/hda6 vga=0x342 resume=/dev/hda7 showopts initrd /boot/initrd-2.6.24-th1
Dabei bedeuten
- default: Nummer (von 0 beginnend) des Eintrages, welcher als Default gebootet werden soll.
- title: Sichtbarer Eintrag im Boot-Menü (entspricht "label" bei LILO).
- kernel: Hier wird der komplette Pfad zum Kernelimage angegeben.
- root: Das Root-Device für die Suche der in den "kernel" und "initrd"-Zeilen angegebenen Dateien. Es hat nichts mit der root=/dev/hda6 Option zu tun, welche das Rootdevice für den gebooteten Kernel angibt!
- initrd: Der komplette Pfad zur Initial Ramdisk.
Alternativ zu obigen Beispiel könnte man auch
kernel (hd0,5)/boot/vmlinuz-2.6.24-th1 root=/dev/hda6 vga=0x342 resume=/dev/hda7 showopts initrd (hd0,5)/boot/initrd-2.6.24-th1
schreiben, wobei man sieht, dass man initrd auch auf anderen Partitionen ablegen kann.
Ein Device wird in der Notation, die GRUB verwendet, als (hdX,Y) angegeben. Dabei steht X für die Festplatte - die Zahl beginnt bei 0 und entspricht der Nummer der gefundenen Festplatten beim Booten; die Reihenfolge wird durch das System-BIOS festgelegt. Y ist die Partition auf der entsprechenden Festplatte, auch hier beginnt die Zählung bei 0. Im Beispiel der GRUB-Konfigurationsdatei oben entspräche (hd0,5) der sechsten Partition auf der ersten Festplatte. Ist /boot eine eigene Partition und nicht Teil der Root-Partition, so ist ggf. bei den Optionen kernel und initrd ein Eintrag der Art "(hd0,0)/vmlinuz-2.6.24-th1" bzw. "(hd0,0)/initrd-2.6.24-th1" nötig, wobei die Angabe der entsprechenden Partition wie oben erklärt erfolgt.
Ausführliche Informationen zur Konfiguration erhält man mit "man grub" bzw. "info grub" und natürlich in /usr/share/doc/packages/grub/. Auch hier gilt wieder, einen neuen Kernel besser erst einmal nicht als Standard zu laden bis sichergestellt ist, dass er einwandfrei lauffähig ist.
Module, die nicht Teil der Kernel-Quellen sind (wie z.B.
Kernelmodule bekannter Grafikchiphersteller) müssen für einen
neuen Kernel nach dem ersten Booten neu übersetzt und installiert
werden! Im Falle der Grafikkarten-Treiber sollte man daher das System
durch Eingabe von "3" am Bootprompt direkt in Runlevel 3 (und nicht in
Runlevel 5, wie es oft der Standard ist) booten. Anschließend kann
man als Root an der Konsole das Kernel-Modul für den
Grafikkartentreiber neu übersetzen und installieren. Siehe hierzu
die entsprechende Dokumentation des Grafikkartentreiberpakets.
Nach der Installation des Kernels (und evtl. dem Anpassen der Datei /etc/modprobe.conf) muss nun der Rechner rebootet werden. Wurden alle Schritte korrekt ausgeführt, so sollte sich der neue Kernel ohne Probleme booten lassen.
Probleme beim Booten des neuen Kernels
Beim Booten des neuen Kernels mag einem entweder an der
Konsole oder aber in /var/log/boot.msg die folgende Meldung
auffallen:
Inspecting /boot/System.map-2.6.13-15.11-default
Loaded 24247 symbols from
/boot/System.map-2.6.13-15.11-default.
Symbols match kernel version 2.6.13.
No module symbols loaded - kernel modules not enabled.
Diese Meldung kommt nicht direkt vom Kernel, sondern von klogd, dem
Kernel Log Daemon. Sie stammt aus der Datei ksym_mod.c der
sysklogd-Quellen. Hier wird eine veraltete Methode verwendet
(get_kernel_syms), um an Informationen über Module zu gelangen. In
"man get_kernel_syms" findet man auch entsprechend einen
Hinweis: Because of these limitations, this system call is deprecated in
favor of query_module. Das Problem produziert letztendlich oben genannte
Fehlermeldung bei Kernel 2.6, obwohl evtl. (falls
CONFIG_MODULES=y in der Konfigurationsdatei .config
steht) Module verwendet werden. Das Module-Handling wird in diesem Fall
trotz der Meldung korrekt funktionieren, daher nicht verunsichern lassen!
Möchte man die Meldung loswerden, so braucht man eine gepatchte
Version von sysklogd.
Beim Booten des neuen Kernels treten mitunter Probleme auf. Das deutet darauf hin, dass einige Punkte beim Konfigurieren oder Installieren des Kernels nicht beachtet wurden. Darunter fallen z.B.:
-
Das System hängt bei LILO oder dem Laden des neuen Kernels:Das deutet darauf hin, dass der Bootloader nicht korrekt installiert ist, siehe dazu auch die genaue Fehlermeldung von LILO. Vermutlich wurde vergessen, /sbin/lilo nach den Änderungen an der Bootloader-Konfigurationsdatei /etc/lilo.conf aufzurufen. Nach dem Reset und dem Booten des alten Kernels ist als Root /sbin/lilo aufzurufen.
-
Das System hängt und die Meldung "Not a compressed kernel image file" erscheint:Vermutlich wurde ein falsches Kernel-Image nach /boot kopiert. Man muss das Kernel-Image ./arch/i386/boot/bzImage (bei i386-Architekturen) verwenden, nicht etwa ./vmlinux. Nach dem Booten des alten Kernels ist der Fehler zu korrigieren - bei LILO anschließend den Aufruf von /sbin/lilo nicht vergessen.
-
Der neue Kernel bootet nicht und die Meldung "No init found" erscheint:Das ist eine typische Meldung, wenn ein falsches Root-Device in der Bootloader-Konfigurationsdatei angegeben wurde. Das sollte überprüft werden. Der Fehler tritt übrigens auch auf, wenn (aus welchem anderen Grund auch immer) kein Init-Programm (/sbin/init, /etc/init oder /bin/init in dieser Reihenfolge) gestartet werden kann. Nach dem Reset kann an der Auswahl am Bootprompt zu Testzwecken das richtige Root-Device über die Option "root=/dev/<device>" übergeben werden, wobei hier dann entsprechend das richtige Device einzusetzen ist. Bootet der neue Kernel, so muss die Bootloader-Konfigurationsdatei abgeändert werden (bei LILO anschließend den Aufruf von /sbin/lilo nicht vergessen).
-
Der neue Kernel bootet nicht und die Meldung "kernel panic: VFS: unable to mount root fs on <device>" erscheint:Die Meldung besagt, dass das Root-Filesystem nicht gemountet werden konnte. Die Ursache ist vermutlich, dass entweder a) die Unterstützung für das Filesystem (ext2, ext3, ReiserFS, xfs, usw.) nicht fest in den Kernel compiliert oder b) das entsprechende Modul für die Unterstützung des Filesystems nicht in die Initial Ramdisk aufgenommen wurde. Es ist auch möglich, dass bei der Erstellung der initrd etwas schief gelaufen ist, vergessen wurde, die initrd neu zu erstellen, oder ein falscher Eintrag für die initrd in der Bootloader-Konfigurationsdatei vorhanden ist. Entsprechend ist zur Lösung des Problems der alte Kernel zu booten und die Einstellungen bezüglich der initrd (evtl. neu erstellen) und der Bootloader-Konfigurationsdatei zu überprüfen.
-
Der neue Kernel bootet nicht und die Meldung "Unable to open an initial console" erscheint:Die Ursache dieser Meldung ist, dass /dev/console in der initrd bzw. wenn solch eine nicht verwendet wird, im Filesystem fehlt. Das wiederum kann mehrere Ursachen haben: Es ist möglich, dass der Bootloader nicht korrekt installiert ist oder eine falsche Root-Partition angegeben wurde. Die Lösungen hierfür wurden bereits genannt. Es ist auch möglich, dass der neue Kernel ohne Unterstützung für virtuelle Terminals (und den zugehörigen Konsolen) übersetzt wurde. Dabei handelt es sich um eine Fehlkonfiguration des Kernels - nach dem Booten des alten Kernels muss der neue Kernel nochmal konfiguriert, compiliert und installiert werden. Als letzte Möglichkeit kommt in Betracht, dass das Device /dev/tty1 gelöscht wurde, was in diesem Zusammenhang aber eher unwahrscheinlich ist.
-
Beim Starten des neuen Kernels erscheint die Meldung "System.map does not match actual kernel":Es wurde vergessen, die Datei System.map des neuen Kernels (mit Versionsangabe) nach /boot zu kopieren. Die Lösung des Problems ist einfach: die zum neuen Kernel gehörende System.map-Datei kann (mit Versionsangabe) nach dem Booten einfach nach /boot kopiert werden, siehe dazu auch das Kapitel "Installation des Kernels".
-
Beim Starten des neuen Kernels wird der Bildschirm schwarz:Eine mögliche Ursache könnten Probleme mit der Framebuffer-Unterstützung sein - in diesem Falle sollte versucht werden, mit dem Bootparameter "vga=normal" zu booten.
-
Nach dem Starten des neuen Kernels funktioniert der NVIDIA/ATI-Treiber (und damit die grafische Oberfläche) nicht mehr:Das Kernel-Modul des NVIDIA/ATI-Treibers muss für den neuen Kernel übersetzt und installiert werden.
-
Beim Booten des neuen Kernels erscheint die Meldung "Waiting for device /dev/<...> to appear" und das System hängt:Mit udev werden Device-Knoten normalerweise automatisch erstellt, was bei genannter Fehlermeldung offensichtlich nicht funktioniert. Mögliche Gründe hierfür sind a) eine gänzlich falsche Angabe des Rootdevice, b) eine fehlerhafte oder falsche Initial Ramdisk, c) eine nicht zum Kernel passende Version von udev, oder d) eine veraltete Version des Skripts "mkinitrd". Entsprechende Möglichkeiten sind zu überprüfen und die Probleme ggf. zu korrigieren.
Bei Boot-Problemen kann unter Umständen auch
folgender Artikel weiter helfen: Oliver Diedrich (odi), "Wenn der Pinguin
nicht abhebt: Erste Hilfe bei Linux-Startproblemen", Praxis
PC-Selbsthilfe: Linux, lilo, grub, ext2, ext3, reiserfs, fsck, c't 26/01,
Seite 130.
Sonstiges
- Manchmal ist es nötig, das Verzeichnis mit den Kernel-Quellen
komplett in den ursprünglichen Zustand zurück zu versetzen
(das gilt nicht für angewandte Patches; das Entfernen von Patches
wurde bereits früher erwähnt). Wie es im richtigen Leben
einen Mr. Proper zum Säubern gibt, so gibt es diesen auch für
den Kernel:
$> cd /usr/src/linux-2.6.x $> make mrproper
Entsprechend kann dieser Befehl auch im Build-Directory angewendet werden.
Durch den hier genannten Befehl wird auch eine eventuell
vorhandene Konfigurationsdatei .config gelöscht!
Möchte man diese erhalten, so muss sie vor dem Ausführen des
obigen Befehls gesichert werden.
- Beim Compilieren des Kernels wird einem sofort auffallen, dass die üppigen Compilermeldungen, wie man sie vielleicht vom Compilieren eines Kernels der 2.4er Serie kennt, nicht mehr angezeigt werden. Die Ausgabe auf dem Terminal-Fenster erscheint wesentlich aufgeräumter. Möchte man wie bei Kernel 2.4 die kompletten Meldungen sehen (was insbesondere beim Auftauchen von Problemen hilfreich sein kann), so muss beim Aufruf von make eine Variable übergeben werden: V=1. Ein Aufruf zum Compilieren von Modulen würde dann z.B. "make V=1 modules" lauten.
- Möchte man alle Dateien innerhalb eines bestimmten Unterverzeichnisses der Kernel-Quellen compilieren, so geschieht das einfach durch Eingabe von "make dir/", wobei "dir" der entsprechende Name des Unterverzeichnisses ist (evtl. inkl. weiterer Unterverzeichnisse). Eine einzige Datei kann mit Hilfe von "make dir/datei.o" compiliert werden, wobei "dir" das entsprechende Unterverzeichnis und "datei.o" das zu erstellende Object-File ist. Eine einziges Kernel-Modul kann mit Hilfe von "make dir/module.ko" erstellt werden, wobei "dir" das entsprechende Unterverzeichnis und "module.ko" das zu erstellende Modul ist.
Durch Eingabe von "make help" erhält man
eine kurze Hilfe (in englisch) über mögliche Targets des
Makefiles. Hier werden die meisten der in diesem Text erwähnten
Befehle kurz zusammengefasst.
- Beim Compilieren des Kernels oder der Module (oder allgemeiner,
beim Ausführen der Targets des Kernel-Makefiles) oder auch beim
Patchen gibt es sehr viele Meldungen auf dem Bildschirm. Es bietet sich
an (insbesondere wenn es zu Fehlern kommt), diese Meldungen in einer
Datei zu speichern, um sie später in aller Ruhe analysieren oder
jemanden um Hilfe fragen zu können. Eine einfache aber effektive
Möglichkeit besteht darin, das Programm "tee" zu nutzen.
Das Programm liest von der Standard-Eingabe und schreibt identisch auf
die Standard-Ausgabe, zusätzlich aber auch in eine Datei. Die
make-Aufrufe können also wie folgt durchgeführt werden (hier
am Beispiel des Targets "bzImage"):
$> make bzImage 2>&1 | tee make_bzImage.log
Es wird ganz normal die Ausgabe auf dem Terminalfenster erfolgen, zusätzlich werden jedoch die Standard-Ausgabe sowie die Standard-Fehlerausgabe in die Datei make_bzImage.log umgeleitet. Zum Umleiten von Standard-Ausgabe und Standard-Fehlerausgabe, siehe auch "Eine kurze Einführung zu Shell-Ausgabeumleitung". - Manchmal mangelt es etwas an Festplattenplatz, insbesondere wenn man mehrere Verzeichnisse mit unterschiedlichen Kernel-Quellen hat. Nachdem ein neuer Kernel compiliert und installiert wurde und nachdem sich herausgestellt hat, dass er einwandfrei bootet und funktioniert, kann man daher im Verzeichnis mit den Kernel-Quellen bzw. dem Build-Directory ein "make clean" ausführen. Dadurch werden die beim Compilieren erstellten Object-Files gelöscht und entsprechend wird weniger Festplattenplatz belegt. Wie schon einmal gesagt: die Kernel-Quellen müssen nicht zwingend unter /usr/src liegen; hat man auf anderen vorhandenen Partitionen mehr Platz, so kann das Verzeichnis mit den Kernel-Quellen auch an einem anderen Ort gelagert werden. Ebenso verleiht das Feature des Build-Directory bei Kernel 2.6 zusätzliche Flexibilität.
Installieren mehrerer Kernel per RPM
Häufig kommt es vor, dass man neben dem eigentlichen Standard-Kernel, der bereits beim Aufspielen der SUSE-Linux Distribution im System installiert wurde, einen anderen SUSE-Kernel (z.B. einen neuen Test-Kernel vom SUSE-FTP-Server) installieren möchte. Der Einfachheit wegen wäre es schön, wenn man das über ein RPM-Kommando tun könnte und nicht die Kernel-Quellen selbst übersetzen müsste, schließlich werden von SUSE explizit Binary-RPMs angeboten (oder man hat sich ein eigenes Kernel-RPM gebaut, siehe oben). Mit
$> rpm -ihv neuer-kernel.rpm
kann man versuchen, das neue Kernel-RPM zu installieren. Sollte das gelingen (evtl. das manuelle Erstellen einer Initial Ramdisk nicht vergessen), so kann man die Bootloader-Konfiguration überprüfen und ggf. anpassen. Damit wäre das Thema auch schon abgeschlossen. Wie bereits früher erwähnt, kann das SUSE-KOTD-Verzeichnis als zusätzliche YaST-Installationsquelle angegeben werden, sodass sich KOTD-Kernel auch einfach über das Software Management-System von SUSE installieren lassen (hier handelt es sich aber nicht um Parallelinstallationen mehrerer Kernel).
Das Kommando "rpm -Uhv neuer-kernel.rpm" wird
den momentan installierten Kernel durch den neuen Kernel
ersetzen! Es ist auf diese Weise nicht möglich, Kernel
parallel zu installieren.
Um herauszufinden, welches Kernel-RPM momentan auf dem
System installiert ist, kann man das Kommando "rpm -qa
'kernel*'" benutzen.
Je nachdem, wie die zu installierende RPM Datei erstellt wurde, kann es beim Installationsversuch aber auch dazu kommen, dass Konflikte gemeldet werden. Was nun? Um das Problem zu lösen, gibt es mehrere Möglichkeiten. Mit dem Kommando
$> rpm -qpl neuer-kernel.rpm
kann man sich im Detail anschauen, welche Dateien im System installiert werden. Sollten dabei keine gravierenden Konflikte mit bereits auf dem System installierten Kerneln festgestellt werden, so kann mit den RPM-Optionen "--force" das neue Kernel-RPM installiert werden. Dadurch wird neben dem Erstellen des Module-Verzeichnisses unter /lib/modules/ (das die Module des neuen Kernels enthält) auch das Kernel-Image unter /boot abgelegt. Eine nötige Initial Ramdisk sollte beim Installieren von SUSE-Kerneln korrekt angelegt werden, ansonsten (z.B. bei selbst erstellten Vanilla-Kernel-RPMs) ist das von Hand wie im Abschnitt über die Installation des Kernels beschrieben nachzuholen. Achtung: ein Entfernen des SUSE Standard-Kernels führt dazu, dass fortan keine Kernel-Updates mehr per YOU eingespielt werden. Nutzt man einen eigenen selbst erstellten Kernel, so ist man selbst für Updates verantwortlich.
Damit sowohl der alte als auch der neue Kernel erfolgreich gebootet werden können, müssen nun ggf. noch die Bootloader-Konfigurationsdateien angepasst werden. Das Prinzip hierfür ist im Abschnitt zum Bootloader beschrieben. Achtung: die Namen und Abschnitte, die in die Bootloader-Konfigurationsdatei eingetragen werden, sollten genau kontrolliert werden, da ansonsten unter Umständen ein Booten nicht mehr möglich ist.
Für den neuen Kernel sind externe Kernel-Module in
der Regel neu zu erstellen (compilieren) und dann zu installieren.
Installieren externer Kernel-Module
Mitunter kommt es vor, dass man externe Kernel-Module, die nicht Teil des Kernel-Quellbaums sind, installieren möchte oder updaten muss, da ein Kernel-Modul in der Regel nur mit genau einer Kernel-Version funktioniert. Kernel-Module können unter Umständen auch mit nicht exakt zum Modul passender Kernel-Version verwendet werden, wenn der sog. "modversions" Mechanismus (kann bei der Kernel-Konfiguration angegeben werden) zur Verfügung steht. In diesem Falle werden jedem Symbol (Variable, Funktion), das der Kernel exportiert, eine Checksumme beigefügt. So steht (hoffentlich) genügend Information zur Verfügung, um Veränderungen am Kernel zu entdecken, die das Modul inkompatibel mit der Kernel-Version machen. In jedem Falle ist es aber besser (sofern möglich), ein Modul exakt für den Kernel zu compilieren, mit dem es dann auch im Betrieb funktionieren soll.
Um ein externes Modul zu übersetzen, müssen gewisse Header-Dateien des Kernels eingebunden werden. In anderen Worten, der Kernel-Source muss korrekt konfiguriert sein. Hat man sich aus den Quellen einen eigenen Kernel compiliert und installiert und danach die Konfiguration des Kernels nicht mehr verändert, so sind die Kernel-Quellen bereits konfiguriert. In allen anderen Fällen sollte man ggf. wie im Abschnitt zum Klonen einer Konfiguration beschrieben vorgehen. Wichtig dabei ist, den Befehl "make modules_prepare" nicht zu vergessen, da dieser unter anderem genau die vom externen Kernel-Modul eingebundenen Header-Dateien (wie z.B. linux/version.h) erzeugt.
Die exakte Vorgehensweise zum Erstellen des externen Kernel-Moduls hängt u.a. davon ab, wie das zugehörige Makefile des Moduls aussieht. In der Regel wird davon ausgegangen, dass der Kernel, für den das Modul zu erstellen ist, momentan läuft, d.h. gebootet ist.
Zum eigentlichen Erstellen des externen Kernel-Moduls wechselt man nun in dessen Source-Verzeichnis. Dort kann mit dem Befehl
$> make -C /pfad/zum/build/directory M=$(pwd) modules
das externe Modul (hoffentlicht) übersetzt und dann (als Root) mit
$> make -C /pfad/zum/build/directory M=$(pwd) modules_install
installiert werden. Wurde ursprünglich kein Build-Directory verwendet, so ist bei der Option "-C" entsprechend das Verzeichnis mit den konfigurierten Kernel-Quellen anzugeben (statt des Build-Directory). Ein Lesen der Dokumentation des Moduls kann weitere Hinweise darauf geben, wie das Modul compiliert werden muss. Im Zweifelsfalle hilft nur, sich das Makefile im Verzeichnis des zu erstellenden Moduls anzuschauen und zu analysieren.
Der Boot-Prozess
Das Booten wird im PC vom BIOS übernommen. Nach dem Abschluss des Power-On SelfTests (POST) versucht das BIOS, den ersten Sektor der ersten Diskette, den sog. Boot-Sektor, zu laden. Schlägt dies fehl, so versucht das BIOS den Boot-Sektor von der ersten Festplatte zu lesen. Aktuelle BIOS-Versionen können die Reihenfolge zum Abfragen der Boot-Sektoren der unterschiedlichen Geräte (Floppy, Festplatte, CD-ROM, Netzwerk, usw.) nahezu beliebig festlegen. Das Booten des Betriebssystems läuft dann meist in mehreren Schritten ab. Da im Boot-Sektor sehr wenig Platz für Code ist, lädt dieser meist einen zweiten Lader nach, usw., bis dann endgültig der eigentliche Betriebssystemkern geladen ist. Der Aufbau eines Boot-Sektors ist prinzipiell recht einfach, seine Länge beträgt stets 512 Bytes. Der Code beginnt bei Offset 0 und der Boot-Sektor endet immer mit der Magic Number 0xAA55.
Das Booten von Diskette ist einfach, da jede Diskette genau einen Boot-Sektor hat. Festplatten können in Partitionen unterteilt sein, daher ist das Booten von Festplatte etwas schwieriger. Das BIOS weiß davon aber erst einmal nichts, sodass es einfach ebenso den ersten Sektor liest, auch Master Boot Record (MBR) genannt. Der MBR besitzt denselben Aufbau wie jeder andere Boot-Sektor, d.h. der Code beginnt bei Offset 0 und bei Offset 0x1FE steht die Magic Number 0xAA55. Am Ende des MBR steht die Partitionstabelle, die stets vier Einträge hat. Jeder Eintrag der Partitionstabelle ist 16 Bytes groß (Boot-Flag: 1 Byte; Kopfnummer des Partitionsbeginns: 1 Byte; Sektor und Zylindernummer des Boot-Sektors: 2 Bytes; Systemcode: 1 Byte; Kopfnummer des Partitionsendes: 1 Byte; Sektor und Zylindernummer des letzten Sektors der Partition: 2 Bytes; relative Sektornummer des Startsektors: 4 Bytes; Anzahl der Sektoren in der Partition: 4 Bytes). Eine Festplatte kann also in vier Partitionen unterteilt werden, die sog. primären Partitionen. Sollte das nicht ausreichen, kann eine sog. erweiterte Partition angelegt werden. Diese enthält wiederum mind. ein logisches Laufwerk. Der Aufbau des ersten Sektors einer erweiterten Partition entspricht einfach dem Aufbau des MBR. Der erste Partitionseintrag dieser erweiterten Partitionstabelle enthält das erste logische Laufwerk der Partition. Der zweite Eintrag wird als Zeiger benutzt, falls weitere logische Laufwerke existieren. Er zeigt dann hinter das erste logische Laufwerk, wo sich wiederum eine Partitionstabelle mit dem Eintrag für das nächste logische Laufwerk befindet. Die einzelnen Einträge der logischen Laufwerke sind also untereinander in einer einfach verketteten Liste verbunden. Der erste Sektor einer jeden primären oder erweiterten Partition enthält einen Boot-Sektor mit dem beschriebenen Aufbau. Da nur von einer dieser Partitionen gebootet werden kann, bestimmt das Bootflag die sog. aktive Partition. Der Code im MBR muss also a) die aktive Partition bestimmen, b) den Boot-Sektor der aktiven Partition mit Hilfe des BIOS laden und c) in den Boot-Sektor bei Offset 0 springen. Ein Bootloader wie LILO oder GRUB kan den MBR mit eigenem Code ersetzen oder den Boot-Sektor einer Partition belegen.
Wird der Bootloader (LILO oder GRUB) in den MBR installiert, so wird der Code dort ersetzt, d.h. der ehemalige MBR überschrieben. Wird der MBR dabei nicht automatisch gesichert, so sollte er zuvor mit
$> dd if=/dev/hda of=MBR.backup bs=512 count=1
gesichert werden. Mit Hilfe von
$> dd if=MBR.backup of=/dev/hda bs=446 count=1
wird der MBR ohne die Partitionstabelle zurückgeschrieben. Achtung: bei diesen Aktionen muss man sehr sorgfältig vorgehen, sonst können sämtliche Daten der Festplatte verloren sein. Soll die alte Partitionstabelle ebenfalls restauriert werden, so ist der Parameter bs=512 zu verwenden. Vorsicht: dabei kann man leicht seine Partitionstabelle zerstören.
Der Bootvorgang geht nun wie folgt vonstatten: Das BIOS selektiert das Gerät zum Booten. Dann wird der Boot-Sektor dieses Gerätes gelesen, in unserem Falle ist das der Boot-Sektor des Bootloaders auf der Festplatte. Dieser lädt das Setup, Dekompressionsroutinen und das komprimierte Kernel-Image in den Speicher. Ein mit "make bzImage" erstellter Kernel kann per BIOS Service "int 0x15" direkt vom niedrigen in den hohen Speicherbereich geladen werden (der Bootloader benutzt dazu die gleichen Techniken, wie sie auch im Kernel-eigenen Boot-Sektor enthalten sind). Nach dem Laden (ein Bootloader wie LILO beendet sich hier) wird arch/i386/boot/setup.S abgearbeitet und zum Eintrittspunkt start: gesprungen. Einige Hardware wird initialisiert und der Prozessor wird in den "Protected Mode" versetzt. Schließlich wird zum Anfang des eigentlichen komprimierten Kerns gesprungen, das entspricht arch/i386/boot/compressed/{head.S,misc.c}. Der Kernel wird nun entkomprimiert und die in arch/i386/boot/compressed/head.S aufgeführten Initialisierungen (z.B. Initialisierung der Page-Tabelle, des Coprozessors, des Stacks, usw.) finden statt. Dann wird start_kernel() aufgerufen. Hierdurch findet nun die "high level" Initialisierung statt, u.a.: architekturspezifisches Setup; Ausgabe des Linux Banner (Version des Kernels, Compiler, etc.); Initialisierung von IRQs, ACPI, Scheduler, Timer, etc.; Auswerten der Boot-Kommandozeile (Boot-Parameter); Initialisierung der Konsole und des dynamischen Ladens von Modulen; Interrupts werden ermöglicht; Ermittelung der BogoMIPS; Initialisierung des Speichermanagements und Ausgabe der Werte (Memory-Zeile); Initialisierung des Proc-Filesystems, diverser Caches und des Thread-Handlings; Auswerten architekturspezifischer Bugs und Aktivierung von Workarounds (z.B. der berühmte CPU "f00f Bug"). Letztendlich wird ein Kernel-Thread init() kreiert, der sämtliche Treiber für die Hardware initialisiert und dann entweder das als Boot-Parameter übergebene Programm init= aufruft oder versucht, /sbin/init, /etc/init oder /bin/init (in dieser Reihenfolge) auszuführen. Falls keines der Programme gefunden wird, wird versucht, eine Rettungskonsole mit der Shell /bin/sh zu starten. Geht das ebenfalls nicht, so tritt ein Kernel-Panic auf. Ansonsten geht das Booten dann mit der Abarbeitung wie in "man init" beschrieben weiter. Es werden normalerweise die unter Linux laufenden Hintergrundprozesse gestartet und dafür gesorgt, dass auf jedem angeschlossenen Terminal das Programm getty läuft. Ein Anwender kann sich dann beim System anmelden.
Der Bootvorgang ist hier nicht komplett und vollständig wiedergegeben, das würde schlicht den Rahmen dieses Textes sprengen. In der Praxis ist es weitaus komplizierter, da z.B. die Verwendung einer Initial Ramdisk oder Multiprozessor-Systeme berücksichtigt werden müssen. Man erhält aber schon in dieser vereinfachten Darstellung einen kleinen Einblick in die Komplexität und die Vorgänge, die im Hintergrund ablaufen.
Der Linux-Kernel: wie alles begann
Linus Torvalds, ein finnischer Student in Helsinki, startete 1991 ein kleines neues Betriebssystem:
From: torvalds@klaava.Helsinki.FI (Linus Benedict Torvalds)
Newsgroups: comp.os.minix
Subject: What would you like to see most in minix?
Date: 25 Aug 91 20:57:08 GMT
Hello everybody out there using minix -
I'm doing a (free) operating system (just a hobby, won't be big and professional like gnu) for 386(486) AT clones. This has been brewing since april, and is starting to get ready. I'd like any feedback on things people like/dislike in minix, as my OS resembles it somewhat (same physical layout of the file-system (due to practical reasons) among other things).
I've currently ported bash(1.08) and gcc(1.40), and things seem to work. This implies that I'll get something practical within a few months, and I'd like to know what features most people would want. Any suggestions are welcome, but I won't promise I'll implement them :-)
Linus (torvalds@kruuna.helsinki.fi)
PS. Yes - it's free of any minix code, and it has a multi-threaded fs. It is NOT protable (uses 386 task switching etc), and it probably never will support anything other than AT-harddisks, as that's all I have :-(.
Sein kleines Projekt fand sehr großen Anklang. Es bildete sich schnell eine Gruppe von Aktivisten, die die Entwicklung des neuen Betriebssystems vorantrieben. Zahlreiche Nutzer testen neue Versionen und tragen dazu bei, die Software von Fehlern zu bereinigen. Linux wird unter offenen und verteilten Bedingungen entwickelt. Mit "offen" ist gemeint, dass jeder, der dazu in der Lage ist, sich an der Entwicklung beteiligen kann. Daher ist eine schnelle, effektive und weltweite Kommunikation notwendig: das Internet. Es ist deswegen nicht verwunderlich, dass ein großer Teil der Entwicklungen von Studenten stammen, die an ihren Universitäten auf das Internet zugreifen können. Diesen Studenten standen anfangs Entwicklungssysteme mit eher bescheidener Ausstattung zur Verfügung, weswegen Linux auch immer noch das 32-Bit Betriebssystem ist, das die wenigsten Ressourcen verbraucht, ohne an Funktionalität einzubüßen. Linux läuft mittlerweile auf fast allem, was Bits und Bytes verarbeiten kann. Die unterstützte Hardware reicht von Embedded-Systemen bis hin zu IBM-Mainframes. Diese Hardwareunabhängigkeit wird von keinem anderen Betriebssystem erreicht.
Die rasante Entwicklung von Linux zeigt sich auch sehr beeindruckend an der Größe der Linux Kernel-Quellen:
- Linux 0.01 (Sept. 1991) 10239 Codezeilen, 0.2 MB
- Linux 0.10 (Dez. 1991) 17750 Codezeilen, 0.4 MB
- Linux 0.99 (Dez. 1992) 81091 Codezeilen, 2.2 MB
- Linux 1.0.0 (März 1994) 176250 Codezeilen, 4.7 MB
- Linux 1.2.0 (März 1995) 310950 Codezeilen, 8.4 MB
- Linux 2.0.0 (Juni 1996) 777956 Codezeilen, 22 MB
- Linux 2.2.0 (Jan. 1999) 1800847 Codezeilen, 52 MB
- Linux 2.4.0 (Jan. 2001) 3377902 Codezeilen, 100 MB
- Linux 2.6.0 (Dez. 2003) 5929913 Codezeilen, 208 MB
Das entspricht einem exponentiellen Wachstum und man kann sich ausdenken, was das für zukünftige Kernel bedeutet :-) Das Ziel, die meiste GNU Software auf Linux zum Laufen zu bekommen, war übrigens bereits mit Version 0.99 realisiert.
Links
Hier einige Links zu Literatur über den Linux-Kernel oder sonstigen Hilfen. Diese Liste ist sicherlich nicht vollständig, sollte aber für eine weitere Informationssuche ausreichen. Bitte beachten: die meiste Literatur zum Linux-Kernel ist in englisch verfasst.
- https://www.kernel.org: die primäre Seite zum Download von Linux Kernel-Quellen
- https://www.linux.org.uk/~davej/docs/post-halloween-2.6.txt: The post-halloween document. (aka, 2.6 - what to expect)
- https://www.kubieziel.de/computer/halloween-german.html: die deutsche Übersetzung des Post-Halloween Documents.
- https://www.kniggit.net/wwol26.html: The Wonderful World of Linux 2.6
- https://thomer.com/linux/migrate-to-2.6.html: Migrating to Linux Kernel 2.6
- https://kernelbook.sourceforge.net/: The Linux Kernel: Blueprints for World Domination
- https://kernelbook.sourceforge.net/kernel-hacking.html/: Unreliable Guide To Hacking The Linux Kernel
- https://www.kernelnewbies.org/: Interesting information for Newbies to the Linux kernel
- https://lkml.org/: the Linux Kernel Mailing List (LKML)
- https://www.kerneltraffic.org/: Kernel Traffic - weekly newsletter about the Linux Kernel Mailing List
- https://www.tldp.org/HOWTO/Kernel-HOWTO/: the Linux Kernel HowTo
- https://www.tldp.org/HOWTO/KernelAnalysis-HOWTO.html: the Linux Kernel Analysis HowTo
- https://www.tldp.org/LDP/lkmpg/index.html: The Linux Kernel Module Programming Guide
- https://www.tldp.org/LDP/lki/index.html: Linux Kernel 2.4 Internals
- https://www.linuxhq.com/: the Linux information headquarters
- https://jungla.dit.upm.es/~jmseyas/linux/kernel/hackers-docs.html: Index of Documentation for People Interested in Writing and/or Understanding the Linux Kernel; eine riesige Link-Liste mit Dokumentation zum Kernel, auch zu speziellen Details im Linux-Kernel
Danksagung
Ich (TH) danke den zahlreichen Ideengebern, die mich einerseits zum Schreiben dieser Anleitung animiert und andererseits dabei unterstützt haben. Insbesondere geht der Dank an Andreas Winkelmann für seine Hilfe beim Verfassen des Textes zum Bootloader GRUB, an Philipp Thomas, der mir einige Details zu den SUSE-Kerneln mitgeteilt hat, an David Haller, der mit seinem Multi-Kernel Howto das Fundament der ersten Version dieses Howtos gebildet hat, und an Jan Engelhardt, der dieses Howto verbessert und überarbeitet und damit auf den neusten Stand gebracht hat. Ferner haben Sebastian Huber, Klaus Ondrich, David Hundenborn, Hans-Robert Wagner, Horst Graffy und Guido Nottebrok (sowie einige leider anonyme Personen) mit ihrem Feedback dazu beigetragen, dieses Howto weiter zu verbessern. Ein ganz besonderes Dankeschön geht an Luigi di Lazzaro, der dieses Howto in die italienische Sprache übersetzt hat!
Disclaimer
Dieser Text erhebt natürlich keinen Anspruch auf Richtigkeit und Vollständigkeit und natürlich wird keine Gewähr für alle Angaben oder daraus entstehender Konsequenzen übernommen. Der Vollständigkeit halber:
There is no warranty for this text. The author provides it 'as is', without warranty of any kind, either expressed or implied, including, but not limited to, the implied warranties of merchantability and fitness for a particular purpose. The entire risk as to the quality of this text is with you. In no event will any author named in this text be liable to you for damages, including any general, special, incidental or consequential damages arising out of any use of this text (including, but not limited to, loss of data, data being rendered inaccurate, or losses sustained by anyone as a result of using this text).
Vielleicht mögen manche Leute gewisse Dinge hier anders sehen, aber dennoch hoffe ich, dass der Grundgedanke derselbe ist und ich hier auch keine all zu großen Bugs eingebaut habe. Wie steht schon sinngemäß im SUSE-Handbuch: Dieser Text entstand im Laufe vieler Stunden. Es bleibt nicht aus, dass im Verlaufe dieser Zeit bessere und weniger gute Abschnitte entstanden. Auch wenn ich eine Menge Fehler beseitigen konnte, so möchte ich doch den Eindruck vermeiden, es handele sich um ein fertiges Produkt. Die dicken Fehler sind nur besser versteckt ;-) Vielleicht habe ich ja die Chance, es beim nächsten Mal besser zu machen. Verbesserungsvorschläge, Korrekturhinweise, Lob und Kritik sind daher stets erwünscht und willkommen.
Dr. Thomas Hertweck ()
Jan Engelhardt ()