Sonntag, 10. April 2011

Linux Kernel kompilieren

Aktuell versuche ich mich im Kernel kompilieren, konfigurieren und installieren.

Die Konfiguration ist dabei sogar der Löwenanteil.
Um es mir den noch einfach zu machen, nutze ich die config Datei unter /boot vom laufenden Kernel.

Damit man sich den Kernel kompilieren kann, benötigt man erst einmal das Archiv des Kernels.

Dieses bekommt man z.B. auf kernel.org.

Am besten nimmt man sich immer den stable oder einen longterm Kernel.
Die stable Kernel sind die stabilen Versionen während die longterm Kernel Langzeitig gepflegt werden.

Ich habe aktuell den Kernel 2.6.38.2 als Basis.
Das Archiv kann man dann unter /usr/src ablegen und per tar -xjf kernel.tar.bz2 entpacken.

Also Ergebnis hat man dann einen Ordner mit dem Schema linux-2.38.2 o.ä.
In diesen wechselt man dann per cd.
Dann kopiert man sich einfach die config Datei des laufenden Kernels.
Unter Debian Squeeze habe ich die config für den Kernel 2.6.32.5
Diese kopiert man dann in das Verzeichnis unter dem Namen .config
Damit wir für den neuen Kernel gerüstet sind, müssen wir die .config auf den neuen Kernel anpassen.

Man hat nun die Wahl zwischen dem leichten und dem schweren Weg.

Der Leicht weg geht über den Befehle "yes "" | make oldconfig"
Das Kommando yes "" sorgt dafür, dass alle Abfragen von make oldconfig einfach mit Enter bestätigt werden.
Somit werden empfohlene Einstellungen genutzt um mögliche neue Einstellungen entweder in den Kernel, also Modul oder gar nicht zu kompilieren.

Der schwere Weg besteht darin, dass man per "make menuconfig" alle Einstellungen für das eigene System anpasst.
Diesen Weg sollte man nur wählen, wenn man weiß welche Hardware vorhanden ist und welche Treiber ggf. erstellt werden sollen.
Eine Fehlkonfiguration führt im schlimmsten Fall dazu, dass der Rechner nicht starten kann weil bestimmte Module nicht erstellt wurden.

Nach der Konfiguration des Kernels können wir diesen kompilieren.

Dabei gibt es ebenfalls 2 Möglichkeiten.

Möglichkeit 1 ist der Debian Weg, der recht einfach ist aber nur für Debian und Derivate gültig ist.
Möglichkeit 2 ist der allgemeine Weg der für alle Distributionen gültig ist.
Dieser Weg benötigt unter Debian nur eine paar Befehle mehr.

Bevor wir mit dem erstellen des Kernels anfangen können, benötigen wir noch zusätzliche Pakete.
Als Grundpakete sollten build-essential, libncurses5-dev und fakeroot vorhanden sein.
fakeroot ist optional dient aber der Sicherheit beim kompilieren.
Damit wird dem Programm make später eine künstliche root Umgebung geboten.

Fangen wir mit Möglichkeit 1 an.
Dies ist der Debian Weg der auch sehr einfach ist und es auch Einsteigern erlaubt sich einen eigenen Kernel zu kompilieren.

Dafür benötigen wir noch das Paket kernel-package.
Dort sind wichtige Tools enthalten mit denen wir den Kernel erstellen und auch fertige .deb Pakete für die Installation über dpkg erstellen können.
Dieses bringt uns das neue Kommando make-kpkg mit dem wir dann den Kernel erstellen und gleich dazu fertige .deb Pakete bekommen.

Da wir mit der Konfiguration soweit fertig sind, können wir den Kernel erstellen lassen.
Dazu nutzen wir den Befehl "make-kpkg -j 4 --initrd kernel_image kernel_headers"

Mit -j 4 geben wir an, dass der Kernel mit 4 parallelen Jobs kompiliert werden soll.
Man sollte nie mehr Jobs nehmen als es Prozessoren gibt.

Bei mehr als 4 Jobs gab es einen internen Speicherfehler im Compiler weshalb der Kernel nicht erstellt werden konnte.

Der Parameter --initrd erstellt die Ram Disk  die benötigt wird damit der Kernel auch booten kann.


Die letzten Parameter Kernel_image und kernel_headers sorgen dafür, dass am Ende des Vorgangs im Elternverzeichnis die fertigen .deb Pakete für den Kernel und die zugehörigen Header Dateien vorhanden sind.
Die Header sollte man immer mit erstellen lassen, da es ggf. Software wie VirtualBox gibt, die beim installieren die Header des laufenden Kernels nutzen wollen um Module gegen den Kernel zu kompilieren.

Dies kann je nach Hardware einige Zeit dauern.
Ein normaler Durchlauf lief bei mir zwischen 10-15 Minuten durch.

Wenn dies erfolgreich durchgelaufen ist, müsst ihr nur per "cd .."  in das Elternverzeichnis wechseln und findet dann die .deb Pakete.

Mit dem Befehle "dpkg -i linux-image-2.6.38.2-2.6.38.2.deb" und dem entsprechenden Aufruf für das Header Paket, könnt ihr den neuen Kernel installieren.

Will man den Kernel wieder entfernen reicht es mit aptitude/apt-get oder direkt per dpkg die Pakete linux-image-2.6.38.2-2.6.38.2 und  linux-header-2.6.38.2-2.6.38.2 zu löschen.
Wie man sehen kann wird der Kernel samt Komponenten wieder gelöscht.

Nun kommen wir zum zweiten und somit zum lagen weg.
Wenn die Konfigurationsdatei bereits angepasst ist, können wir direkt mit dem kompilieren beginnen.
Dazu nutzen wir den Befehl make.

Damit wir aber nicht ewig warten müssen, können wir den Vorgang parallelisieren.
Dazu dient ein einfaches make -j 4.
Die Option ähnelt der Option von make-kpkg.
Grund dafür ist eigentlich, dass make-kpkg auch nur make benutzt und somit die Option an den eigentlichen make Befehl weitergereicht wird.

Als Build Ziel, was man noch als letzten Parameter angeben muss, nutzen wir all.
Somit wird der Kernel und die Module kompiliert.

Der Befehl lautet dann nur "make -j 4 all".
Nun heißt es warten, da das kompilieren Zeit braucht.
Auch hier dauerte es bei mir 10-15 Minuten.

Nach dem kompilieren müssen wir den Kernel und die Module installieren.
Ebenfalls muss eine ramdisk für den Kernel angelegt werden und zusätzlich noch der Bootloader angepasst werden.
Entgegen der Vermutung brauchen wir dafür nur wenig Aufwand.

Die Installation erledigen wir mit "make install && make modules_install".
Damit wird der Kernel und die Module an die richtigen Stellen kopiert, was unnötige cp Aufrufe vermeidet.

Nach dem dieser Befehl durchgelaufen ist, erzeugen wir die Ramdisk.
Diese wird mit "update-initrd -c -k 2.6.38.2" erzeugt und unter /boot abgelegt.
Nun muss nur noch grub angepasst werden.
Dazu reicht ein einfaches update-grub und schon ist alles erledigt.


Will man den Kernel wieder entfernen, muss man hier erst einmal die Ramdisk korrekt entfernen.
Dazu muss man nur den Befehl "update-initrd -d -k 2.6.38.2" eingeben.
Dies entfernt die Ramdisk sauber.
Nun muss man nur noch unter /boot die restlichen Dateien entfernen und erneut "update-grub" ausführen.
Somit entfernt Grub die Menüeinträge und der Kernel ist sauber entfernt.

Insgesamt ist das Kernel kompilieren keine große Magie.
Es braucht lediglich etwas Zeit und ein paar Befehle.

Leider hat ein neuer Kernel aber nicht nur Vorteile.
Leider war die VirtualBox Version von Squeeze nicht mit dem neuen Kernel kompartibel, weshalb sich das Modul des Kernel Treibers für Virtualbox nicht übersetzen lies.
Somit lief Virtualbox zwar aber es lies sich keine VM ausführen.
Hier müsste man sich selbst die aktuelle Version von Virtualbox beziehen und installieren.

Da ich aber ein sauberes Debian bevorzuge, werde ich warten bis alles wichtige in testing ist und werde dann einfach umsteigen und parallel stable laufen lassen.

Ansonsten viel Spaß beim Kernel "backen" und verköstigen :)

Keine Kommentare: