Kernel kompilieren / anpassen / patchen


Es ist möglich unter Linux einen neuen Kernel zu kompilieren, anzupassen oder zu patchen. Die Kernelquellen sind auf dem System (falls installiert), im Verzeichnis „/usr/src/“ enthalten. Auf der Internetseite www.kernel.org sind ständig aktelle Kernel und Patches erhältlich.




Grundsätzlich werden zum kompilieren eines Kernels die Programme „gcc“ (GNU Compiler Collection) und „make“, ein Build-Management-Tool um automatisiert Arbeitsschritte zu steuern, benötigt.


In den Beispielen wurde ein Debian 6 Linux mit folgender Kernelversion verwendet.

root@galactica:~# uname -r
2.6.32-5-686





Kernel herunterladen und bereitstellen


Der gewünschte Kernel kann mit folgenden Kommando heruntergeladen werden.

root@galactica:/usr/src# wget http://www.kernel.org/pub/linux/kernel/v3.0/linux-3.2.35.tar.bz2




Entpacken des Kernels mit folgenden Befehl.

root@galactica:/usr/src# tar -xvjf linux-3.2.35.tar.bz2




Zunächst sollte ein Softlink mit der Bezeichnung „linux“ auf das Verzeichnis mit der Kernelquelle erstellt werden.

root@galactica:/usr/src# ln -s linux-3.2.35/ linux





Kernel konfigurations Setup


Um einen Kernel kompilieren zu können, wird vom Kompiler die Datei „.config“ ausgewertet, die entweder aus der bestehenden Kernel konfiguration übernommen („make oldconfig“) oder neu erstellt werden kann. Ist im zu konfigurierenden Kernelverzeichnis keine „.config“ vorhanden, wird in der Regel die bestehende Konfigurationsdatei des aktuellen Kernels verwendet oder komplett neu mit Standardwerten erstellt.


Bei den Abfragen gibt es folgende Einstellungsmöglichkeiten:

  • y ⇒ (yes) Die Komonente wird in den statischen Teil des Kernels integriert.
  • m ⇒ (modular) Komponente wird als Modul integriert.
  • n ⇒ (no) Komponente wird nicht in den Kernel integriert.
  • ? ⇒ Zeigt Informationen zur Kerneloption.




Für das Konfigurations Setup der Kernelparameter können nun verschiedene Kommandos verwendet werden.



make config


Der Befehl „make config“ ist jedoch wenig konfortabel, weil hier eine ganze Menge an Parameter über die Kommandzeile abgefragt werden.


root@galactica:/usr/src/linux-3.2.35# make config
  HOSTCC  scripts/basic/fixdep
  HOSTCC  scripts/kconfig/conf.o
  SHIPPED scripts/kconfig/zconf.tab.c
  SHIPPED scripts/kconfig/zconf.lex.c
  SHIPPED scripts/kconfig/zconf.hash.c
  HOSTCC  scripts/kconfig/zconf.tab.o
  HOSTLD  scripts/kconfig/conf
scripts/kconfig/conf --oldaskconfig Kconfig
#
# using defaults found in /boot/config-2.6.32-5-686
#
...
*
* Linux/i386 3.2.35 Kernel Configuration
*
*
* General setup
*
Prompt for development and/or incomplete code/drivers (EXPERIMENTAL) [Y/n/?]
...





make oldconfig


Benutzt die bestehende Konfiguration eines vorhandenen Kernels und fragt nur Einstellungen ab, die im alten Kernel nicht vorhanden sind.



make menuconfig


Um auf das „ncurses“ Bibliothek basierende Konfigurationsmenü zugreifen zu können, muß das Paket „libncurses5-dev“ (Debian ) oder „ncurses-devel“ (Red Hat ) installiert werden und kann dann mit dem Befehl „make menuconfig“ aufgerufen werden.






make xconfig


Ein Konfigurationsfrontend für das ein X-Window System. Hierfür müssen die Pakete „qt3-devel“, „qt4-devel“ (Red Hat ) oder „qt3-dev-tools“, „qt4-dev-tools“ (Debian ) sowie „g++“ und „build-essential“ installiert werden. Bei Fehlermeldungen sollten weitere Abhängigkeiten der Pakete überprüft werden.






make gconfig


Ein Konfigurationsfrontend auf der Basis von GTK+. Um dies zu installieren, bitte alle benötigten Abhängigkeiten der jeweiligen Linux Distributionen überprüfen.


Wurden alle gewünschten Einstellungen vorgenommen, Datei speichern und Konfigurationsprogramm beenden.

#
# configuration written to .config
#





Kompiliervorgang starten


Zum kompilieren eines Kernels bis zur Version 2.4 sind folgende Kommandos notwendig.


  • make dep ⇒ Überprüft Abhängigkeiten in den Quelldateien und erstellt in den Verzeichnissen der Kernel Quellen die Datei .depend.
  • make clean ⇒ Entfernt Fragmente von ausgeführten Komiliervorgängen und alte .depend Dateien.
  • make bzImage ⇒ Erstellt den statischen Teil des Kernels in das Verzeichnis /arch/i386/boot/bzimage.
  • make modules ⇒ Erzeugt die Module zur Kernelversion.




Seit der Kernelversion 2.6 ist zum kompilieren des Kernels und zum erzeugen der Module nur noch das Kommando „make“ erforderlich.




root@galactica:/usr/src/linux-3.2.35# make
  HOSTLD  scripts/kconfig/conf
scripts/kconfig/conf --silentoldconfig Kconfig
  HOSTCC  arch/x86/tools/relocs
  CHK     include/linux/version.h
  UPD     include/linux/version.h
  CHK     include/generated/utsrelease.h
  UPD     include/generated/utsrelease.h
...
...
...




Wenn der Kompiliervorgang abgeschlossen ist, kann der statische Teil des Kernels und die Datei „system.map“ nach „/boot“ kopiert werden. Die Dateien kann man manuell kopieren oder automatisch mit.

  • make install


root@galactica:/usr/src/linux# make install
sh /usr/src/linux-3.2.35/arch/x86/boot/install.sh 3.2.35 arch/x86/boot/bzImage \
		System.map "/boot"







Kernelmodule einbinden


Die erzeugten Module müssen für den neuen Kernel eingebunden werden.


  • make modules_install


root@galactica:/usr/src/linux# make modules_install
  ...
  ...
  INSTALL /lib/firmware/sb16/mulaw_main.csp
  INSTALL /lib/firmware/sb16/alaw_main.csp
  INSTALL /lib/firmware/sb16/ima_adpcm_init.csp
  INSTALL /lib/firmware/sb16/ima_adpcm_playback.csp
  INSTALL /lib/firmware/sb16/ima_adpcm_capture.csp
  DEPMOD  3.2.35




Die Module für den Kernel 3.2.35 sollten nun im Verzeichnis „/lib/modules“ vorhanden sein.

root@galactica:/lib/modules# ls -l
insgesamt 8
drwxr-xr-x 4 root root 4096 11. Dez 18:08 2.6.32-5-686
drwxr-xr-x 3 root root 4096 13. Dez 20:28 3.2.35





Initial Ramdisk erstellen


Die „initial ramdisk“ ist ein reservierter Bereich im Arbeitsspeicher, der vom Kernel wie eine Festplattenpartition behandelt wird. Die „initial ramdisk“ enthält ein Abbild des Dateisystems und Treiber welche zum Start des Systems benötigt werden.



initrd


Zum Erstellen von initrd-Abbildern wird das Programm „mkinitrd“ verwendet. Die „initrd“ ist jedoch mittlerweile veraltet und wurde von „initramfs“ abgelöst. In vielen neueren Linux Systemen funktioniert das Programm „mkinitrd“ auch nicht mehr.



initramfs


Das „initramfs“ (Initial Ram Filesystem) bezeichnet ein komprimiertes Archiv, das Dateien enthält, die beim Systemstart in den Arbeitsspeicher geladen werden und kann seit dem Kernel 2.5.46 verwendet werden. Zum erstellen eines Initial Ram Filesystems wird das Programm „mkinitramfs“ verwendet.


Um das Programm nutzen zu können muß das Paket „initramfs-tools“ (Debian ) installiert sein.


root@galactica:/usr/src/linux# mkinitramfs -o initrd.img-3.2.35

Erzeugt ein Initial Ram Filesystem für den kompilierten Kernel.


root@galactica:/usr/src/linux# mv initrd.img-3.2.35 /boot

Dies sollte dann noch nach „/boot“ verschoben werden und danach „update-grub“ ausgeführt werden.


Sollte es beim neustart des Systems zu einer Fehlermeldung kommen, dass die Kernelmodule nicht geladen werden können …!




Hier liest die Datei initrd.img-3.2.35 die Module von Kernel 2.6.32-5-686 ein.


Danach sollte die Datei „initrd.img-3.2.35“ gelöscht werden.

root@galactica:/boot# rm initrd.img-3.2.35




Und wie folgt neu erstellt werden.

root@galactica:/boot# update-initramfs -cvk initrd.img-3.2.35
...
...
Adding binary /sbin/blkid
Adding library /lib/libblkid.so.1
Adding library /lib/libuuid.so.1
Calling hook dmsetup
Building cpio /boot/initrd.img-3.2.35.new initramfs



root@galactica:/boot# update-grub
Generating grub.cfg ...
Found background image: /usr/share/images/desktop-base/desktop-grub.png
Found linux image: /boot/vmlinuz-3.2.35
Found initrd image: /boot/initrd.img-3.2.35
Found linux image: /boot/vmlinuz-2.6.32-5-686
Found initrd image: /boot/initrd.img-2.6.32-5-686
done

Bei Debian Systemen kann man das Kommando „update-grub“ verwenden.


# grub.conf generated by anaconda
#
# Note that you do not have to rerun grub after making changes to this file
# NOTICE:  You have a /boot partition.  This means that
#          all kernel and initrd paths are relative to /boot/, eg.
#          root (hd0,0)
#          kernel /vmlinuz-version ro root=/dev/VolGroup00/LogVol00
#          initrd /initrd-version.img
#boot=/dev/sda
default=0
timeout=5
splashimage=(hd0,0)/grub/splash.xpm.gz
hiddenmenu
title Scientific Linux SL (2.6.18-308.20.1.el5)
        root (hd0,0)
        kernel /vmlinuz-2.6.18-308.20.1.el5 ro root=/dev/VolGroup00/LogVol00
        initrd /initrd-2.6.18-308.20.1.el5.img
title Scientific Linux SL (2.6.18-308.16.1.el5)
        root (hd0,0)
        kernel /vmlinuz-2.6.18-308.16.1.el5 ro root=/dev/VolGroup00/LogVol00
        initrd /initrd-2.6.18-308.16.1.el5.img
title Scientific Linux (2.6.18-164.2.1.el5)
        root (hd0,0)
        kernel /vmlinuz-2.6.18-164.2.1.el5 ro root=/dev/VolGroup00/LogVol00
        initrd /initrd-2.6.18-164.2.1.el5.img

Bei Red Hat Systemen muß man die Datei „/boot/grub/grub.conf“ manuell bearbeiten.


Nach einem Neustart sollte es funktionieren.







dracut


Das Programm „dracut“ ist eine universelle Schnittstelle zum Erzeugen einer „initramfs“, die von allen Distributionen genutzt werden kann. Hierfür muß das Programm „dracut“ installiert werden.


[root@galactica boot]# dracut initrd-3.2.35.img 3.2.35



Ist der Systemstart mit dem neuen Kernel gut gegangen, sollten noch die Kernellogfiles überprüft werden, z.B. mit dmesg.






Sollen neue Funktionen in die Kernel Quellen integriert werden, können Patches verwendet werden. Viele Linux Distibutionen bieten in ihren Repositories Kernel Patch Dateien an um z.B. zusätzliche Treiber in das System einzubinden. Hierfür wird das Programm „patch“ verwendet.


Syntax:

  • patch [opt] [org-datei] [patch-datei]
  • patch -p[num] < [patch-datei]




Optionen:

  • --dry-run ⇒ Testlauf des patches. Gibt das Ergebnis nach STDOUT aus.
  • -p[num] ⇒ Num (Zahl) gibt an, wie die Patchdatei gefunden werden soll. Beispiel: p0 = /pfad/zum/patch, p1 = pfad/zum/patch, p2 = zum/patch, p = patch.
  • -R ⇒ Patch entfernen.
  • -s ⇒ Nur Fehlermeldungen ausgeben.
  • -b ⇒ Legt Backups von veränderten Dateien an (.orig).




Beispiel:

root@home:/usr/src# bzip2 -dc patch-3.4.23.bz2 | patch -p1 --dry-run

Hier wird ein Kernelpatch simuliert (--dry-run), die bzip2 Optionen -d dekomprimiert und -c sorgt dafür, dass die Ausgabe nach STDOUT erfolgt.


Dateien, bei denen der Patch fehlgeschlagen ist werden als .rej (reject) Dateien gespeichert.


Ein Patch sollte immer zuerst mit der Option --dry-run simuliert werden.





Cloud