Aus Linux-Magazin 08/2014

Kernel- und Treiberprogrammierung mit dem Linux-Kernel – Folge 75

© psdesign1, Fotolia

Ubuntu bringt von Haus aus Kernel mit, die für die meisten Einsatzzwecke taugen. Die aktuelle Version 14.04 der Distribution eignet sich aber auch für erste eigene Versuche mit dem Konfigurieren, Übersetzen und Installieren des Linux-Kerns.

Der jüngste Ubuntu-Spross, die Nummer 14.04, setzt einen Linux-Kernel in der Version 3.13 ein, allerdings um Treiber aus Kernel 3.14 ergänzt ([1], [2]. Da es sich um eine Release mit Longterm-Support (LTS) handelt, kann der Kernel mehrere Jahre im Einsatz sein. Die Ubuntu-Firma Canonical hat sich aus diesem Grunde auch bereit erklärt, die weitere Pflege dieser Kernelversion zu übernehmen.

Vorgefertigt

Die von Ubuntu eingesetzten Kernel sind eierlegende Wollmilchsäue, die sowohl auf karg als auch auf üppig ausgestatteten Maschinen rund laufen. Wer aber sein System optimieren möchte, einen superaktuellen Treiber benötigt, die jeweils neuesten Kernel testen will oder mit seinem Betriebssystemkern einfach nur rumspielen möchte, muss selbst Hand anlegen.

Zum Spielen oder Optimieren ist nicht unbedingt ein neuer Kernel zu übersetzen. Viel lässt sich bereits durch eine zielgerichtete Konfiguration bewirken. Ausgangspunkte dafür bilden die virtuellen Verzeichnisse »/proc/« und »/sys/« sowie die Übergabe von Kernelparametern beim Hochfahren.

Über das Lesen und vor allem das Schreiben der in den virtuellen Verzeichnissen zu findenden Dateien lässt sich das System auf die jeweilige Plattform anpassen. Mit Superuser-Rechten ausgestattet kann der Anwender so beispielsweise den I/O-Scheduler durch Lesen und Schreiben der Datei »/sys/block/sda/queue« austauschen ([4], [5]).

Kernelparameter wie etwa »threadirqs« zum Aktivieren von Threaded Interrupts (sie erlauben unterschiedliche Prioritäten für Interrupts) setzt man in der Datei »/etc/default/grub« über die Variable »GRUB_CMDLINE_LINUX« :

GRUB_CMDLINE_LINUX="threadirqs"

Wer diese Datei ändert, muss allerdings anschließend in einer Konsole als Superuser »update-grub« aufrufen.

Auch zum Kompilieren von Kernelmodulen wie beispielsweise Treibern ist kein selbst generierter Kernel erforderlich. Die hierfür benötigten Headerdateien sind ebenso unter »/usr/src/« vorhanden wie die zugehörige Kernelkonfiguration. Ist ein Kernelmodul zu backen, reicht also bei korrektem Makefile erfreulicherweise ein Aufruf von »make« aus.

Treiber kompilieren

Wer ein Modul oder einen Treiber aus einem neueren Kernel braucht, sollte vorab unter http://kernel.ubuntu.com/~kernel-ppa/mainline/?C=N;O=D nachsehen (Abbildung 1). Canonical generiert regelmäßig Pakete mit dem aktuellen Linux-Quellcode und legt sie sortiert auf dem Server ab. Die Pakete sind für die jeweils aktuelle Entwicklerversion von Ubuntu kompiliert.

Abbildung 1: Die Linux-Distribution Ubuntu stellt auf ihren Servern aktuelle Kernelpakete zur Verfügung.

Abbildung 1: Die Linux-Distribution Ubuntu stellt auf ihren Servern aktuelle Kernelpakete zur Verfügung.

Für Trusty Tahr finden sich Kernel der Version 3.14 und die ersten beiden RCs von 3.15, ab dann begann die Entwicklung von Ubuntu 14.10. Andererseits lassen sich mit »dpkg -i Paketname« auch Pakete installieren, die ursprünglich für eine andere Version gedacht waren. Dazu lädt man die Paketdateien per Browser oder mit dem Kommandozeilen-Programm »wget« herunter.

Zwei Pakete sind erforderlich: Eines für den eigentlichen Kernel und eines für die Header, damit sich auch außerhalb der normalen Kernelquellen installierte Treiber (beispielsweise von Virtualbox) kompilieren lassen. Die Namen der Pakete sind sehr ausladend:

http://kernel.ubuntu.com/~kernel-ppa/mainline/v3.15-rc3-utopic/linux-headers-3.15.0-031500rc3-generic_3.15.0-031500rc3.201404280035_amd64.deb

Der eigentliche Paketname (Eintrag nach der Pfadangabe) reicht bis zum Unterstrich, im Beispiel also »linux-headers-3.15.0-031500rc3-generic« . Danach folgt eine Versionsangabe, deren letzter Teil schließlich die Plattform repräsentiert, hier einen 64-Bit-PC (»amd64« ).

Generisch oder zackig

Canonical generiert die Kernel mit zwei unterschiedlichen Konfigurationen. Die Version »lowlatency« gewährleistet auf Kosten der Effizienz etwas kürzere Latenzzeiten als die »generic« -Version. Sie findet Einsatz vor allem im Multimedia-Umfeld (Audio), doch die Unterschiede sind minimal.

Per »dpkg -r Paketname« lassen sich die Pakete wieder entfernen. Allerdings ist danach wieder ein »update-grub« auf der Kommandozeile fällig, um auch den Bootloader wieder in einen konsistenten Zustand zu bringen.

Neuer als aktuell

Die paketierten Kernel sind natürlich mit der Standardkonfiguration von Ubuntu kompiliert. Für einen Kernel mit abweichender Konfiguration bietet es sich schließlich an, direkt auf den Torvalds’schen Kernel zurückzugreifen (Abbildung 2).

Abbildung 2: Vom Quelltext über das Konfigurieren bis zum Installieren und Grub-Updaten: In fünf Schritten zum neuesten Kernel.

Abbildung 2: Vom Quelltext über das Konfigurieren bis zum Installieren und Grub-Updaten: In fünf Schritten zum neuesten Kernel.

Der Quellcode steht als komprimiertes Archiv auf http://www.kernel.org zum Herunterladen bereit (Abbildung 3). Auf der Hauptseite finden sich die aktuellen Versionen, unterhalb von http://www.kernel.org/pub/linux/kernel/ sind zusätzlich ältere Versionen und auch Patches verfügbar.

Abbildung 3: Die Quellen aller Mainline-Kernel finden sich bei Kernel.org.

Abbildung 3: Die Quellen aller Mainline-Kernel finden sich bei Kernel.org.

Für jede Kernelversion und für jedes Patch sind drei Paketdateien abgelegt, die sich nur durch die verwendeten Kompressionsverfahren unterscheiden. Darüber hinaus gibt es eine Datei, die die zugehörige digitale Signatur enthält.

Letztere sollten Anwender unbedingt zusammen mit dem komprimierten Quellcode herunterladen. Sie erlaubt es, die Integrität und Authentizität der dekomprimierten Archivdateien zu überprüfen (Abbildung 4). Das Quellcodepaket dekomprimiert man zunächst – abhängig vom eingesetzten Kompressionsverfahren – mit dem Kommando »gunzip« , »bunzip2« oder »xz -d« .

Abbildung 4: Das Krypto-Programm Gnu PG prüft anhand der digitalen Unterschrift die Authentizität des Quelltext-Downloads.

Abbildung 4: Das Krypto-Programm Gnu PG prüft anhand der digitalen Unterschrift die Authentizität des Quelltext-Downloads.

Außerdem sind noch die digitalen Unterschriftenproben von Linus Torvalds (für den Kernel selbst) und Greg Kroah-Hartman (für die Patches) erforderlich, sofern nicht schon auf dem Rechner vorhanden. Aktuell lautet die Zertifikat-ID von Torvalds »00411886« , die von Kroah-Hartman »6092693E« . Die Unterschriftenproben, die Zertifikate also, installiert Gnu PG mit folgender Kommandozeile:

gpg --keyserver hkp://keys.gnupg.net--recv-keys 00411886 6092693E

Besitzt der Anwender die korrekten Unterschriftenproben, setzt er mit dem Kommando

gpg --edit-key 00411886

und dem Unterkommando »trust« die Vertrauensstufe hoch. Das verhindert eine ansonsten auftretende Vertrauenswarnung bei der Überprüfung der Authentizität. Anschließend ruft der Benutzer

gpg --verify linux-<version>.sign

auf. Gnu PG meldet typischerweise nach kurzer Zeit zurück, dass die Unterschrift korrekt und das Paket unverändert ist. Das Paket lässt sich anschließend per »tar« unterhalb von »/usr/src/« auspacken. Da das Verzeichnis Root gehört, arbeitet der Anwender dabei wie im weiteren Verlauf als Superuser, zu dem jedermann mit »sudo su« wird.

Kompilieren ohne Rootrechte

Wer aus Sicherheitsgründen nicht durchgehend als Root arbeiten möchte, legt zuerst ein Unterverzeichnis »mainline« in »/usr/src/« an und stellt liberale Zugriffsrechte ein, etwa mit »chmod 777 mainline« . Dann kann er das Auspacken des Quellcodes und das Generieren als normaler User durchführen. Erst die Installation erfordert wieder Superuser-Berechtigungen.

Alternativ zum Download per HTTP bietet sich »git clone« an, um damit per Versionskontrolle direkt auf das von Linus Torvalds gepflegte Quellcode-Archiv zuzugreifen [3].

Konfigurieren

Ist der Quellcode installiert, fehlt noch die Konfiguration. Am geschicktesten ist es, die Konfiguration des installierten Ubuntu-Kernels als Basis zu verwenden. Die ist für Kernel 3.13.0-24 gleich an zwei Stellen zu finden, einmal unter dem Namen »/usr/src/linux-headers-3.13.0-24/.config« und alternativ unter »/boot/config-3.13.0-24-generic« . Die exakte Versionsnummer ist allerdings anzupassen, denn Canonical bringt regelmäßig aktualisierte Versionen heraus.

Menügeführt

Um die Kernelkonfiguration zu ändern, ruft der Anwender im Quellcodeverzeichnis »make menuconfig« auf. Meldet Make einen Fehler, liegt das meistens daran, dass das Paket »libncurses-dev« nicht installiert ist, »apt-get install libncurses-dev« hilft in diesem Fall. Aufgrund der vielen Optionen erweist sich die Konfiguration als mühsam und bis die gewünschte Option gefunden ist, muss man so manchen Menüpunkt auswählen.

Hilfreich ist die Suche, die der Benutzer mit »/« aktiviert. Beim Beenden fragt »make menuconfig« , ob es die Konfiguration speichern soll. Bejaht das der User, schreibt das Programm die versteckte Datei ».config« . Im Anschluss stößt das Kommando »make -j 4« das Übersetzen von Kernel und Modulen an. Die Option »-j 4« sorgt dafür, dass Make mehrere Prozessorkerne zum Kompilieren nutzt, in diesem Fall vier. Das Generieren ist eine gute Gelegenheit, sich einen Kaffee zu holen: Bei der Ubuntu-Default-Konfiguration dauert es gut und gern 45 Minuten, selbst auf aktueller Hardware.

Installieren

Die Installation schließlich erfolgt in mehreren Schritten. Zuerst platziert der Superuser durch das Eingeben von »make modules_install« im Quellcodeverzeichnis des Kernels die soeben generierten Module unterhalb von »/lib/modules/« . Den Kernel selbst kopiert er danach zusammen mit der Konfiguration in das Verzeichnis »/boot/« . Er trägt den Namen »vmlinuz_Version« , die Konfigdatei heißt »config-Version« .

Neben dem Kernel mit seinen Modulen benötigt Ubuntu noch ein initiales RAM-Filesystem (siehe Kasten “Initram-FS”). Dieses generiert das Kommando:

Initram-FS

Das initiale RAM-Filesystem, kurz Initram-FS, ist eine Art Ramdisk, die ein typischerweise rudimentäres Userland [6] beherbergt. Dort finden sich insbesondere Programme zur Systemkonfiguration und zum Laden von Treibern. Ubuntu setzt es als so genanntes Early Userland ein, um dadurch den Kernel ohne Treiber (die sich nämlich dann im Initram-FS befinden) ausliefern zu können. Nach dem erfolgreichen Laden der Treiber wechselt Ubuntu auf die eigentliche Rootpartition über und löscht das Early Userland wieder aus dem RAM. Dadurch bleiben keine überflüssigen Treiber oder Konfigurationen im Hauptspeicher. Für den User ist der Vorgang unsichtbar.

In Abgrenzung zur Ramdisk benötigt Initram-FS keinen Dateisystemtreiber, da es direkt auf den internen Schnittstellen für den Dateizugriff aufsetzt. Dadurch ist es effizienter und auch nicht größenbeschränkt. Gibt es aktualisierte oder zusätzliche Treiber ist im Übrigen nur das Initram-FS neu zu installieren.

update-initramfs -c -k <version>

Das Ergebnis landet ebenfalls im Verzeichnis »/boot/« . Der Befehl »update-grub« schließlich analysiert das Verzeichnis »/boot/« und generiert aufgrund der Ergebnisse eine neue Bootloader-Konfiguration. Damit steht beim nächsten Booten der neue Kernel zur Auswahl beziehungsweise der Bootloader startet ihn automatisch.

Die gesamte Abfolge der Kommandos für einen selbst gebauten Mainline-Kernel zeigt Listing 1.

Listing 1

Mainline-Kernel bauen und installieren

01 # Superuser werden
02 sudo su
03 # Vorbereitung (Pakete und Quellcode installieren)
04 apt-get install build-essential libncurses-dev git
05 cd /usr/src/
06 mkdir mainline
07 cd mainline
08 git clone https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
09 cd linux
10 cp ../../linux-headers-3.13.0-24-generic/.config .
11 # Kernel konfigurieren ("exit" und abspeichern)
12 make menuconfig
13 # Kernel generieren
14 make -j 4
15 # Installation
16 make modules_install
17 cp arch/x86_64/boot/bzImage /boot/vmlinuz-3.15.0-rc5
18 cp .config /boot/config-3.15.0-rc5
19 update-initramfs  -c -k 3.15.0-rc5
20 # Bootloader aktualisieren
21 update-grub

Verkorkste Kernel entfernen

Wer den selbst erzeugten Kernel wieder loswerden möchte, muss einige Dateien löschen. Das sind im Verzeichnis »/boot/« der Kernel (»vmlinuz-Version« ), die Konfiguration (»config-Version« ) und das Initram-FS (»initrd-Version« ). Die zugehörigen Module entfernt man durch Löschen des Verzeichnisbaums »/lib/modules/Version« . Anschließend folgt noch ein »update-grub« , und alle Spuren sind beseitigt.

Achtung: Linuxer sollten peinlich darauf achten, nur die selbst generierte Version zu entfernen, sonst droht ein nicht mehr lauffähiges System. Die benötigten Kommandos fasst Listing 2 zusammen.

Listing 2

Selbst gebauten Kernel entfernen

01 cd /boot
02 rm config-3.15.0-rc5
03 rm vmlinuz-3.15.0-rc5
04 cd /lib/modules
05 rm -rf 3.15.0-rc5
06 update-grub

Kernelpaket bauen

Alternativ zu dem gezeigten Vorgehen kann der Benutzer mit Hilfe des Kommandos »make-kpkg« Debian-Kernelpakete generieren. Das ist vor allem dann sinnvoll, wenn er den Kernel auf einer anderen Maschine respektive auf mehreren Maschinen einsetzen möchte. Hierzu installiert er als Root per

apt-get install kernel-package fakeroot

zwei Pakete. Kernelpakete lassen sich anschließend mit Hilfe eines eigenen Kommandos generieren. In der Handhabung ist das etwas einfacher, insgesamt benötigt es aber auch mehr Zeit. Im Code einiger Release-Kandidaten für Kernel 3.15 gibt es zudem einen Bug, der zum Abbruch des Kommandos führt.

Beim Aufruf (Listing 3) sind Parameter anzugeben, vor allem welche Debian-Pakete das Tool produzieren soll (»kernel_image« und »kernel_headers« ), dass es ein Initram-FS erzeugt (»–initrd« ) und dass es mehrere Prozessor-Cores zur Abarbeitung einsetzen soll (»–jobs« ).

Listing 3

Debian-Kernelpaket bauen

01 make-kpkg --initrd --jobs 4 --rootcmd fakeroot --config menuconfig \
02 --append-to-version=-linuxmag kernel_image kernel_headers

Auch hier sind nicht unbedingt Rootrechte erforderlich. Wichtig ist die Option »–rootcmd« , falls man das Kommando mit gewöhnlicher Benutzerkennung aufruft. Für das Bauen der Pakete benötigt »make-kpkg« nämlich eigentlich Rootrechte, die es mittels Fakeroot emuliert. Darüber hinaus existieren weitere Optionen, beispielsweise »–config menuconfig« , über die sich die Kernelkonfiguration anpassen lässt.

Die generierten Pakete legt das Werkzeug in einem Verzeichnis unterhalb des Quellcodeverzeichnisses »/usr/src/« ab. Sie lassen sich mit »dpkg -i« installieren und mit »dpkg -r« deinstallieren.

Am liebsten selbst gemacht

Wie gezeigt macht Ubuntu 14.04 es Admins und Entwicklern einfach, eigenen Kernelcode oder gar eigene Kernel zu verwenden. Die wesentlichen Komponenten sind bereits installiert und vorkonfektioniert. Lohn der Mühe sind meist eine bessere Hardware-Unterstützung sowie ein schnelleres und stromsparenderes System. (mhu)

75

Infos

  1. Martin Loschwitz, “Ubuntu 14.04 – Nutztier für lange”, Linux-Magazin 06/14, S. 54
  2. Ubuntu Kernel Team, “Ubuntu 14.04 Kernel Version and Configuration”: https://lists.ubuntu.com/archives/ubuntu-devel/2014-April/038226.html
  3. Linux-Quellcode-Archiv von Linux Torvalds: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
  4. Quade, Kunst, “Kern-Technik – Folge 19”: Linux-Magazin 03/05, S. 88
  5. Quade, Kunst, “Kern-Technik – Folge 20”: Linux-Magazin 04/05, S. 108
  6. Quade, Kunst, “Kern-Technik – Folge 39”: Linux-Magazin 05/08, S. 98

Der Autor

Eva-Katharina Kunst ist seit den Anfängen von Linux Fan von Open Source. Jürgen Quade, Professor an der Hochschule Niederrhein, hat mit “Embedded Linux lernen mit dem Raspberry Pi” Ende April 2014 sein drittes Linux-Buch veröffentlicht.

DIESEN ARTIKEL ALS PDF KAUFEN
EXPRESS-KAUF ALS PDFUmfang: 4 HeftseitenPreis €0,99
(inkl. 19% MwSt.)
LINUX-MAGAZIN KAUFEN
EINZELNE AUSGABE Print-Ausgaben Digitale Ausgaben
ABONNEMENTS Print-Abos Digitales Abo
TABLET & SMARTPHONE APPS Readly Logo
E-Mail Benachrichtigung
Benachrichtige mich zu:
0 Kommentare
Älteste
Neuste Beste Bewertung
Inline Feedbacks
Alle Kommentare anzeigen
Nach oben