|
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.