Linux-Kernel-Debugging ist ein heikles Thema. Während Windows & Co. schon seit gefühlten Ewigkeiten einen Kerneldebugger zur Verfügung stellen, hat es bei Linux 16 Jahre gedauert, bis Torvalds bereit war einen "Kerneldebugger light" in die Quellen aufzunehmen. Seit 2008 ist der »kgdb«
ein Bestandteil des Linux-Kerns, etwas später kam die Erweiterung »kdb«
dazu.
Mitgeliefert: KDB
Dabei stellt »kdb«
die einfachste Möglichkeit dar, den Kernel zu untersuchen. Viele Distributionen, beispielsweise auch Ubuntu, integrieren den KDB, allerdings ohne ihn gleich scharf zu schalten. Das ist jedoch schnell erledigt, denn sobald der Debugger die Schnittstellen kennt, über die er Kommandos bezieht und an die er die Ausgaben schicken soll, ist er auch schon aktiviert. Zur Auswahl stehen dafür die Konsole, repräsentiert durch das Keyboard und das Schlüsselwort »kbd«
, sowie die serielle Schnittstelle (»ttyS0«
).
Die Schlüsselwörter schreibt der Superuser mit Hilfe von »echo«
in die zum Kerneldebugger gehörende Konfigurationsdatei »kgdboc«
. Die Variante für die Konsole (Keyboard) lässt sich unter Berücksichtigung der Option »kms«
mit der folgenden Kommandozeile konfigurieren:
echo kms,kbd > /sys/module/kgdboc/parameters/kgdboc
Achtung: »kbd«
steht hier für Keyboard und nicht für den KDB. Mit dieser Konfiguration friert das System ein, sobald eine Kernelkomponente abstürzt oder ein Kernelmodul die Funktion »panic()«
aufruft. Root kann das System aber auch von Hand zum Debuggen einfrieren, indem er das Kommando
echo g >/proc/sysrq-trigger
eingibt oder die vier Tasten [Strg]+[Alt]+[S-Abf]+[G] gleichzeitig drückt. [G] steht dabei für das Kommando, um in den interaktiven Modus des Debuggers zu wechseln. Ein »help«
im interaktiven Modus zeigt die weiteren Kommandos an. Der Anwender kann Speicherzellen auslesen und schreiben, die Prozessliste oder die letzten Kernelnachrichten anzeigen sowie Breakpoints setzen. Eines der wichtigsten Kommandos ist »go«
, denn es veranlasst den Kernel dazu, seine Arbeit wieder aufzunehmen, als wäre gar nichts gewesen. Tabelle 1 listet die wichtigsten KDB-Kommandos auf.
Tabelle 1: Wichtige Kommandos des Kerneldebuggers KDB
Nur Assembler-Code
So umfangreich die Möglichkeiten auch sind, zwei Probleme schränken den Einsatz des eingebauten Debugger-Frontends ein: Erstens unterstützt KDB kein Debugging auf Hochsprachen-Niveau und zeigt dem Anwender nur Assembler-Code. Zweitens funktioniert er nur einwandfrei, wenn er entweder für die serielle Schnittstelle »ttyS0«
konfiguriert ist oder von einer normalen Konsole aus aufgerufen wird.
Immerhin ist es dank Kernel Mode Switching (KMS) mittlerweile möglich, den Debugger auch aus dem grafischen Modus mit X.org zu verwenden. In diesem Fall schaltet der Debugger bei der Aktivierung auf die erste Konsole, um von hier aus das System zu untersuchen. Sobald der Anwender ihn per »go«
beendet, schaltet der Debugger wieder zurück zur grafische Oberfläche. Allerdings funktioniert das nicht in jedem Fall, es gibt beispielsweise Probleme in einer mittels Virtualbox virtualisierten Umgebung. Außerdem muss der Superuser KMS explizit durch Angabe des Schlüsselworts »kms«
aktivieren.
Die klassische Variante des Kerneldebuggings nutzt aber ohnehin die serielle Schnittstelle zur Ein- und Ausgabe. Dumm nur, dass man zwei Rechner dafür benötigt. Außerdem besitzen moderne Desktop-PCs, Note- oder Netbooks gar keine serielle Schnittstelle mehr.
Doch genau hier kann eine Virtualisierungslösung aushelfen. Schnell lässt sich mit Virtualbox ein Rechner zusammenklicken und mit einer seriellen Schnittstelle versehen. Diese ist als so genannte Hostpipe zu konfigurieren (Abbildung 1). In Virtualbox kann ein Linux, beispielsweise Ubuntu 11.10, als so genanntes Debug-Target laufen. Den Kerneldebugger des Targets schaltet Root mit folgendem Kommando scharf:
Abbildung 1: Debuggen eines virtualisierten Linux-Systems auf dem lokalen Rechner: Die serielle Schnittstelle konfiguriert der Virtualbox-Anwender als Hostpipe.
echo ttyS0,115200 > /sys/module/kgdboc/parameters/kgdboc
Zur Kommunikation mit dem Debugger des Targets muss auf dem Hostsystem ein Terminalprogramm installiert sein, hier bietet sich »minicom«
an. Leider kann Minicom nicht direkt mit der Hostpipe (im Beispiel »/tmp/com1«
) kommunizieren. Daher ist weitere Software erforderlich, die zwischen Hostpipe und Minicom vermittelt. Das übernimmt »socat«
, sodass das gesamte Setup neben Virtualbox mit einem Linux aus Socat und Minicom besteht (siehe Abbildung 2).
Abbildung 2: Debuggen des Kernels in einer virtualisierten Umgebung.