Hallo
Welt - als Kernel Modul
|
Ich werde hier einfach den Quellcode angeben und ihn danach Zeile für Zeile auseinandernehmen:
#include <linux/module.h> #include <linux/sched.h> int init_module(void) { printk("<1>Hallo Welt!\n"); printk("<1>aufrufender Prozess: \"%s\" (Prozess-ID %i)\n", current->comm, current->pid); return 0; } void cleanup_module(void) { printk("<1>Und Tschüss Welt!\n"); }Dies ist nicht das einfachste Hallo Welt, das denkbar ist, sondern gibt gleich noch etwas aus "das interessant ist", nämlich den Namen des Programms das das Laden veranlaßt hat (vermutlich insmod) sowie seine Prozess-ID. Ein Wort noch an alle Ungeduldigen, die gleich probieren das Programm zu übersetzen: es wird nicht mit allen Kernel-Versionen funktionieren, sollte jedoch mit allen neueren (so ab 2.x) funktionieren. Die Meldung wird unter Umständen nicht auf dem Bildschirm erscheinen, sondern in /var/log/messages protokolliert werden (kommt auf die Einstellungen des Loglevels an, siehe man klogd(8)). Außerdem darf das Programm nicht gelinkt werden, sondern muß als Objekt-Code erzeugt werden. Und damit nicht genug: es müssen noch einige Symbole definiert werden und die Optimierung sollte eingeschaltet werden. Falls das jetzt furchtbar kompliziert klingt versuche ich einfach mit dem entsprechenden Befehl etwas Licht ins Dunkel zu bringen:
cc hallo.c -c -o hallo.o -Wall -O -DMODULE -D__KERNEL__Die Option -Wall sorgt dafür daß alle Warnings ausgegeben werden - eine Option die man immer verwenden sollte um nicht irgendwelche Ungereimtheiten unter den Teppich zu kehren.
Das Laden des Moduls erfolgt mit insmod hallo.o während das Entladen mit rmmod hallo vorgenommen wird.
Doch nun für die Leute die gerne wissen wollen was da jetzt passiert ist: der Quellcode Zeile für Zeile.
#include <linux/module.h> #include <linux/sched.h>Die Header-Dateien die wir einbinden unterscheiden sich erheblich von denen, die man für eine Applikation benötigt. Mehr noch: man sollte niemals die Bibliotheken für eine Applikation einbinden, denn der Kernel hat alle Funktionen die man benötigt selbst definiert und da das Modul durch insmod zum laufenden Kernel gelinkt wird (und nicht zu einer Bibliothek wie z.B. libc) können auch nur die vom Kernel zur Verfügung gestellten Symbole aufgelöst werden.
int init_module(void)Dies ist der Einstiegspunkt für das Modul. Es entspricht in etwa der Funktion int main(int argc, char *argv[]) normaler Applikationen im User-Space. Diese Funktion sollte im Allgemeinen dazu dienen daß sich das Modul anmeldet und seine Fähigkeiten bekanntgibt, damit es in Zukunft für diese Zwecke herangezogen werden kann.
printk("<1>Hallo Welt!\n");Dies hier ist jetzt die Ausgabe von "Hallo Welt!". printk() ist hierbei quasi die Kernel-Version von printf() und funktioniert auch ähnlich. Die "<1>" gibt hierbei die Dringlichkeit der Nachricht an. Sie sollte (sofern der Loglevel der Konsole stimmt bzw. klogd richtig konfiguriert ist) auf der Konsole erscheinen, kann aber auch bei laufendem klogd in /var/log/messages landen.
printk("<1>aufrufender Prozess: \"%s\" (Prozess-ID %i)\n", current->comm, current->pid);Nun wird es etwas trickreich. Weil "Hallo Welt!" an sich etwas langweilig ist lassen wir uns den Aufrufer und seine Prozess-ID ausgeben. current ist hierbei ein Zeiger auf den aktuellen Prozess dessen "Wünsche" bearbeitet werden. Hier sehen wir die beiden Elemente comm das den Namen des Programmes angibt, und pid, die Prozess-ID. Wir sehen auch daß printk() ebenfalls %i und %s wie printf() behandelt.
void cleanup_module(void)Dies ist die Funktion die beim Entladen aufgerufen wird, bevor der Code endgültig aus dem laufenden Kernel entfernt wird. Sie sollte dazu verwendet werden das Modul aufzuräumen und dem Kernel mitzuteilen, daß es nicht mehr vorhanden sein wird und seine Fähigkeiten nicht mehr verfügbar sind.
printk("<1>Und Tschüss Welt!\n");Die letzte Meldung die unser Modul von sicht gibt - danach ist es weg.
Ich hoffe daß nun alle Klarheiten beseitigt sind und die gröbste Neugierde ersteinmal befriedigt ist. Wenn ich bei der Modul-Programmierung weiter durchgestiegen bin werde ich weitere Einblicke in den Linux-Kernel zu geben versuchen.