ChatGPT generiert auf Wunsch auch Kernel-Code. Ob der tatsächlich zu gebrauchen ist, prüfen wir in einem kleinen Selbsttest.
Kein wissenschaftliches Paper, keine Konferenz, kein (Software-)Produkt und keine Schlagzeile, bei der einem nicht das Wort KI entgegenspringt. Wo künstliche Intelligenz nicht schon eingebaut ist, wurde zumindest etwas mithilfe von KI entwickelt oder sogar produziert. Man mag versuchen, das als Hype abzutun, doch wer sich schon einmal intensiv mit ChatGPT auseinandergesetzt hat, erkennt das Potenzial: Artifical Intelligence (AI) verändert unser Leben nachdrücklich.
ChatGPT basiert auf einem Sprachmodell, das sich Generative Pre-trained Transformers (GPT) nennt. Es wurde mit unzähligen Texten inklusive Programmcode trainiert und generiert auf dieser Basis neue Texte gemäß der Wahrscheinlichkeit, mit der bestimmte Worte in einem gegebenen Kontext vorkommen (siehe Kasten “Large Language Models”). Es erstaunt und kann sogar beunruhigen, was auf einer solch primitiven Basis möglich ist.
Im letzten Jahrhundert stellten noch Informationen das zentrale Gut dar. Bis vor Kurzem war es dann die Fertigkeit, mit Google und Co. Informationen zu suchen, zu finden und aufzubereiten. Das alles ist Schnee von gestern. Die heranwachsende Generation muss nur noch lernen, richtig Fragen zu stellen, die Antworten zu reflektieren und sie zu bewerten. Dann bekommt sie die gewünschten Informationen gebrauchsfertig verpackt direkt ausgeliefert.
Sprachmodelle wie ChatGPT können auch programmieren. Beschreibt man die Aufgabe detailliert genug und gibt die Programmiersprache vor, erscheint wenige Sekunden später ein gut kommentierter Quellcode inklusive Erläuterungen bezüglich Aufbau und Funktionsweise. Als Dreingabe erhält man die notwendigen Schritte, um aus dem Quellcode ein Executable zu zaubern.
ChatGPT programmiert dabei nicht nur einfache Applikationen, sondern behauptet von sich, auch Kernel-Code erstellen zu können. Das derzeit eingesetzte Modell GPT 4.0 hat dabei immerhin Trainingsdaten bis zur Kernel-Version 6.5 vom August 2023 verinnerlicht. Allerdings darf man dabei nicht vergessen, dass ChatGPT auf Nachfragen selbstkritisch einräumt, in Hinsicht auf Hardware, Nebenläufigkeit, Synchronisation und Speichermanagement unsicher zu sein.
Large Language Models
Bei einem Large Language Model handelt es sich um ein neuronales Netz, das mit großen Datenmengen aus Büchern, Artikeln, Webseiten und Quellcodes trainiert wurde. Damit vermag es aus einem Textkontext heraus Vorhersagen bezüglich des nächsten zu erwartenden Worts zu treffen und neue Texte in natürlicher Sprache zu generieren. Auf diese Weise kann das Modell Inhalte “verstehen”, zusammenfassen oder in andere Sprachen transkribieren.
Zu den bekanntesten Sprachmodellen gehören GPT (Generative Pre-trained Transformer) von OpenAI, BERT (Bidirectional Encoder Representations from Transformers) von Google und das quelloffene LLaMA (Large Language Model Meta AI) von Meta. Die Leistungsfähigkeit der Modelle definiert man dabei häufig in Form der Parameter. Die größte Variante von LLaMA 3.1 basiert beispielsweise auf 405 Milliarden Parametern.
Die meisten Large-Language-Modelle basieren auf der 2017 entwickelten Transformer-Architektur, die besonders effizient Zusammenhänge in großen Textmengen erkennt. Interessieren Sie sich für die detailliertere Funktionsweise (Abbildung 1), liefert die Webseite von Brendan Brycroft eine sehr anschauliche Visualisierung [2].

Abbildung 1: Brendan Brycroft hat eine Visualisierung für die Funktionsweise von Large-Language-Modellen entwickelt. Quelle: Brendan Brycroft (https://bbycroft.net/llm)
Zu Wort kommen lassen
Code, der im Kontext eines Betriebssystemkerns abläuft, ist besonders diffizil zu programmieren. Ein Betriebssystemkern gehört nicht nur wegen des schieren Codeumfangs zu den komplexesten Softwaregebilden. Auch die fehlenden Schutzmechanismen und die Nähe zur Hardware machen die Programmierung nicht gerade einfach.
Um erfolgreich ein stabiles Kernel-Modul zu erstellen, benötigt man umfangreiche und detaillierte Kenntnisse rund um die Programmierung und das Betriebssystem. Dazu gesellen sich die hohen Anforderungen an Effizienz. Da stellt sich die Frage, inwieweit ChatGPT tatsächlich gebrauchsfähigen Kernel-Code produzieren kann und ob sich dadurch das Leben von Entwicklern vereinfacht.
Probiert man das mit dem Prompt “Schreibe mir einen Linux-Kernel-Treiber, der bei einem lesenden Zugriff ‘Hello, world’ zurückgibt” aus, dann erscheint die Antwort von ChatGPT auf den ersten Blick beeindruckend: Mit gespielter Leichtigkeit spuckt es einen gut kommentierten Kernel-Code für ein »hello_world.c« aus. Mit dazu gibt es eine Erklärung, ein Makefile und Hinweise, wie man den Code zu einem Kernel-Modul kompiliert, es lädt, testet und schließlich wieder aus dem Kernel entfernt. Also ein Rundum-sorglos-Paket?
Das Makefile und die Kommandos zum Umgang mit dem Kernel-Code sehen tatsächlich recht gut aus. Allerdings fällt auf, dass die von ChatGPT avisierte Umgebung für die Kommandos schlicht Unfug ist: So verwendet die KI für den Aufruf von Make eine Go-Umgebung und prüft den Ladezustand des Moduls mit Perl (Abbildung 2). Das ist kein Drama, dürfte den meisten Fragestellern überhaupt nicht auffallen und tut vor allem der Funktionalität keinen Abbruch. Tatsächlich korrigierte sich die KI in unseren folgenden Versuchen diesbezüglich.
Lernwillig
Dass ChatGPT statt des erwarteten Gerätetreibers eine Implementierung über das Proc-Filesystem vorzieht, ist zumindest in Ordnung und vielleicht sogar zielführend, wenn es darum geht, einen leichten Einstieg in die Kernel-Programmierung zu erhalten.
Allerdings schlägt das Generieren des Kernel-Moduls durch einen Make-Aufruf fehl: Eine Vielzahl an Fehlermeldungen flutet den Bildschirm, irgendetwas stimmt mit der verwendeten Datenstruktur »struct file_operations« nicht. Im Dialog mit den Fehlermeldungen konfrontiert, erklärt ChatGPT die Inkompatibilität und versucht es mit einer aktualisierten Version, die sich tatsächlich kompilieren, laden und erfolgreich testen lässt (Abbildung 3). Sie nutzt die in aktuellen Kerneln verwendete Struktur »struct proc_ops«. Prima!

Abbildung 3: ChatGPT verwendet häufig veraltete Funktionen. Dabei kennt die KI sich mit aktuellen Kerneln aus.
Allerdings weist die Implementierung eine Besonderheit auf, die nicht den Unix-Gepflogenheiten entspricht. Damit eine Applikation die Daten von “Hello, world” lesen kann, muss sie ausreichend Speicher zur Verfügung stellen. Nur einen Teil-String zu lesen, unterstützt das Kernel-Modul überraschenderweise nicht.
Hilfreiche Erläuterungen
Eine Warnung, die noch beim Generieren aufploppt, erklärt ChatGPT übrigens auf Nachfragen sehr ausführlich, inklusive mehrerer Optionen, um sie auszublenden. Die Erläuterungen sind sehr hilfreich.
Ob ChatGPT auch komplexere Szenarien beherrscht, soll ein nächster Auftrag klären. Wir weisen das Sprachmodell an, einen Kernel-Treiber für ein Producer-Consumer-System zu generieren, um zu prüfen, was ChatGPT in Sachen Kontrollfluss und Schlafenlegen so drauf hat. Beim Lesezugriff auf eine Gerätedatei sollen die bei einem Schreibzugriff abgelegten Daten zurückgeliefert werden. Gibt es keine Daten, wird der Task im Fall des »BLOCKING«-Zugriffsmodus so lange schlafen gelegt, bis Daten vorliegen (Abbildung 4). Umgekehrt soll bei einem vollen Eingangspuffer der auf dieselbe Gerätedatei schreibende Task dösen, bis wieder Platz im Puffer frei wird.

Abbildung 4: Über einen Ringpuffer soll die KI zeigen, ob sie einen korrekten Kontrollfluss mit Schlafenlegen und Aufwecken programmieren kann.
Zuweilen von gestern
Tatsächlich liefert ChatGPT wieder einen erfreulich gut kommentierten Treibercode, der sich sogar auf Anhieb zu einem Kernel-Modul generieren lässt. Funktional scheint auf den ersten Blick ebenfalls alles zu passen – doch das scheint nur so. Einen Profi dürfte es überraschen, dass die KI die Funktion »register_chrdev()« verwendet, um das Kernel-Modul als Treiber anzumelden. Das ist zwar schlank und elegant, aber hoffnungslos veraltet. Zeitgemäß wählt man besser die Variante über ein Objekt vom Typ »struct cdev«.
Bedenklicher ist allerdings der Umstand, dass der KI-generierte Code eine Race Condition enthält (Listing 1). Als Race Condition bezeichnet man eine Situation, in der das Ergebnis einer Operation vom zeitlichen Verlauf oder – anders formuliert – vom Zufall abhängt. Mal funktioniert es, mal funktioniert es nicht – sehr unschön. Konkret kann im vorliegenden Fall ein Absturz im Kernel auftreten, wenn ein Task versucht, auf das kurz zuvor per Rmmod entladene Kernel-Modul zuzugreifen (Abbildung 5).

Abbildung 5: Entfernt man ein Kernel-Modul per Rmmod aus dem Speicher, das noch ein aktiver Task nutzt, kommt es zu einem Absturz.
Listing 1
Fehlerhafte Funktion
// Aufräumfunktion des Moduls
static void __exit prodcons_exit(void) {
mutex_lock(&buffer_lock);
device_open = 0; // Gerät deaktivieren
// Wecke alle wartenden Prozesse auf
wake_up_interruptible(&read_queue);
wake_up_interruptible(&write_queue);
mutex_unlock(&buffer_lock);
// Entferne das Gerät
device_destroy(prodcons_class, MKDEV(major_number, 0));
class_unregister(prodcons_class);
class_destroy(prodcons_class);
unregister_chrdev(major_number, DEVICE_NAME);
printk(KERN_INFO "prodcons: Gerät entfernt\n");
}
Aus der Nase ziehen
Darauf aufmerksam gemacht, gibt sich ChatGPT schuldbewusst und legt prompt neuen Code nach, der angeblich das Problem beseitigt. Dem Laien wird es vermutlich nicht auffallen, aber ChatGPT leistet dabei nur halbe Arbeit. Zwar verringert sich die Wahrscheinlichkeit einer Race Condition, doch kann sie immer noch auftreten. Erst im dritten Versuch gelangte ChatGPT, unterstützt durch zielführende Hinweise, zum Erfolg (Listing 2).
Hier zeigt sich ein elementares Problem für den Kernel-Neuling: Der von ChatGPT erzeugte Code weist häufig Fehler und Seiteneffekte auf, die sich nur mit einigem Know-how erkennen lassen. Die KI kennt viele Aspekte und sogar Details, kann das aber das Gesamtbild nicht überblicken und ist auf eine führende Hand angewiesen.
Im nächsten Versuch soll ChatGPT einen Kernel-Treiber für einen Raspberry Pi 4 schreiben, der über eine Gerätedatei eine LED ansteuert. Es geht also um einen Hardwarezugriff. Schreibt man eine 1 auf die Gerätedatei, leuchtet die Diode, bei einer 0 geht sie aus.
Listing 2
Race Condition manuell abgewehrt
// Aufräumfunktion des Moduls
static void __exit prodcons_exit(void) {
mutex_lock(&buffer_lock);
device_open = 0; // Gerät deaktivieren
// Wecke alle wartenden Prozesse auf
wake_up_interruptible(&read_queue);
wake_up_interruptible(&write_queue);
// Warte, bis alle offenen Operationen beendet sind
if (open_count > 0) {
mutex_unlock(&buffer_lock);
wait_for_completion(&on_exit);
} else {
mutex_unlock(&buffer_lock);
}
device_destroy(prodcons_class, MKDEV(major_number, 0));
class_unregister(prodcons_class);
class_destroy(prodcons_class);
unregister_chrdev(major_number, DEVICE_NAME);
printk(KERN_INFO "prodcons: Gerät entfernt\n");
}
Ein Flop
Wieder erhält man ausführlich dokumentierten Code, das passende Makefile und die Anweisung, wie man alles zum Laufen bekommt. Der Code lässt sich direkt kompilieren, aber das Laden klappt nicht. Im Syslog findet sich der Eintrag GPIO-Anforderung fehlgeschlagen.
Mit dieser Meldung konfrontiert, diskutiert die KI eine Reihe von Fehlermöglichkeiten durch. Die Ursache des Hängers: Vor geraumer Zeit hat sich die Adressierung der GPIOs geändert, die GPIO-17 wird mittlerweile über GPIO-529 angesprochen. Damit umgeht Linux das Problem, dass in einem Rechner mehrere GPIO-Controller eingebaut sein können. Da es damit mehrere GPIOs mit derselben Nummer geben kann, muss man je nach Controller einen anderen Offset auf die Nummer addieren. Das weiß das LLM aber offensichtlich nicht. Der aufmerksame Neuling dagegen hätte das bei der Beschäftigung mit der Materie schnell herausgefunden.
Mit einer entsprechenden Änderung lässt sich der Code schließlich laden, doch die versprochene Gerätedatei bleibt das System schuldig. Den Code zum automatischen Anlegen der Gerätedatei hat ChatGPT gar nicht mit generiert, und es unterschlägt auch eine Erklärung, wie man sie von Hand erzeugt.
Darauf angesprochen, gibt der Chatbot die notwendigen Hinweise aus und liefert einen frischen Code, der das automatische Anlegen der Gerätedatei erlegt. Jetzt gibt es allerdings Probleme mit dem Kompilieren: Die Kernel-Entwickler haben die Parametrierung der Funktion »class_create()« geändert, ChatGPT verwendet jedoch die alte Variante. Wer diese Kleinigkeit kennt, repariert den Code, und nach dem Generieren und Laden lässt sich die LED tatsächlich ansteuern.
Erfinderisch
Studiert der Profi den von ChatGPT vorgeschlagenen Code, fällt auf, dass der das längst als veraltet (“deprecated”) gekennzeichnete Interface verwendet. Wie immer zeigt sich der Bot schuldbewusst und generiert binnen weniger Sekunden eine aktualisierte Variante, die auf das standardkonforme GPIO-Deskriptor-Interface setzt.
@:Dabei stößt die KI aber an ihre Grenzen. Zum einen erfindet sie mit »gpiod_get_from_of_node()« mal eben eine neue Funktion, die es im Kernel nicht gibt, zum anderen verschweigt sie diese Nettigkeit. Hinzu kommt, dass der Code korrekterweise einen Devicetree [1] voraussetzt, also eine Hardwarebeschreibung in Textform. Die Vorschläge der KI, wie man an die notwendigen Devicetree-Einträge kommt, sind inkonsistent und funktionieren nicht. Darauf verwiesen, erzeugt die immer geduldige KI ein sogenanntes Devicetree Overlay, das aber letztlich mit dem Raspberry Pi inkompatibel ist. Selbst mit guten Zureden gelingt es am Ende nicht, ChatGPT ein laufendes und dem aktuellen Standard entsprechendes Kernel-Modul generieren zu lassen.
Das Experiment, gleich mehrere GPIOs reservieren zu lassen, scheitert ebenfalls. Das von der KI vorgeschlagene Aufräumen im Fall eines Problems bei der Reservierung ist schlichtweg falsch und enthält subtile Fehler. ChatGPT fühlt sich bei einfachen, überschaubaren und abgegrenzten Aufgaben sichtlich wohler. Dazu gehört etwa die Aufgabe, Code für einen Kernel-Thread zu generieren, der in regelmäßigen Abständen im Syslog eine Nachricht ausgibt.
Halluzinationen
ChatGPT erzeugt Code, der sich direkt kompilieren, laden und ausführen lässt und prima aussieht. Auf die hinterlistige Nachfrage, ob er nicht vielleicht doch eine Race Condition enthalten könnte, zeigt sich ChatGPT gewohnt devot. Die KI erläutert unverzüglich, wo das Problem mit der Race Condition liegt – doch die gibt es in Wirklichkeit gar nicht.
Entsprechend sinnlos ist auch der Lösungsvorschlag (Listing 3), den nicht existenten kritischen Abschnitt durch ein ziemlich sinnlos eingestreutes Mutex zu schützen, ein »mutex_lock()« direkt gefolgt von einem »mutex_unlock()«.
Listing 3
Verwirrte KI
// Kernel-Modul beenden
static void __exit my_module_exit(void) {
printk(KERN_INFO "Kernel-Modul wird entladen: Stoppe Kernel-Thread\n");
if (thread_st) {
// Kernel-Thread stoppen und sicherstellen, dass er beendet ist
kthread_stop(thread_st);
// Warten, bis der Thread tatsächlich beendet wurde
mutex_lock(&thread_mutex); // Mutex sperren, um Race Conditions zu verhindern
mutex_unlock(&thread_mutex);
printk(KERN_INFO "Kernel-Thread erfolgreich gestoppt\n");
}
}
Fazit
Die Kernel- und Treiberprogrammierung gehört definitiv zu den anspruchsvolleren Gebieten der Softwareentwicklung. Im Prinzip ist es also sehr beeindruckend, mit welchen Ergebnissen ChatGPT bereits aufwartet: In Sekunden erscheint gut kommentierter und lesbarer Code, nebst einer ausführlichen Erklärung zum Code selbst, zur Generierung des Kernel-Moduls und zum Test.
Doch an dieser Stelle beginnen dann die Schwierigkeiten. Häufig lässt sich das Kernel-Modul nicht direkt generieren. Die KI ist nicht auf der Höhe der Zeit und verwendet oft veraltete Interfaces. Weiß das LLM nicht weiter, erfindet es sogar Funktionen und outet sich erst bei explizitem Nachfragen.
Zwar kennt sich ChatGPT augenscheinlich in den Tiefen des Linux-Kernels relativ gut aus, hat aber aufgrund eines fehlenden Kontextverständnisses Probleme, die unterschiedlichen Aspekte miteinander zu verknüpfen. Das führt dazu, dass der generierte Code subtile Fehler enthält, die ein Einsteiger nicht erkennt. Vermutet der Laie Fehler, wo es tatsächlich keine gibt, zeigt sich ChatGPT verunsichert und verschlimmbessert.
Diese Einschränkungen sollen nicht darüber hinwegtäuschen, dass die KI insbesondere für erfahrene Entwickler eine große Hilfe sein kann. ChatGPT vermag komplexe Konzepte zu erklären, kann offene Fragen fundiert beantworten, erstellt Code-Templates und hilft bei der Fehlersuche. Anfängern eröffnet die KI eine Möglichkeit, in den Themenkomplex Kernel- und Treiberprogrammierung einzusteigen.
Dabei gilt es aber stets im Hinterkopf zu behalten, dass sich der generierte Code, so er sich denn kompilieren und laden lässt, ohne professionelle Überarbeitung nicht für produktive Systeme eignet. Wohlgemerkt: All das gilt nur für ChatGPT 4.0 – mal sehen, was GPT 5.0 so alles auf dem Kasten haben wird. (jlu)
Disclaimer
Wie sieht es eigentlich mit diesem Artikel aus? Hat da möglicherweise ChatGPT als Ghostwriter seine virtuellen Finger im Spiel gehabt? Entwarnung: Nein, dieses gute Stück Text ist handgemacht – noch.
Der Autor
Jürgen Quade, Professor an der Hochschule Niederrhein, offeriert für Unternehmen Schulungen zu den Themen Treiberprogrammierung und Embedded Linux.
Infos
- Kern-Technik: Jürgen Quade, “Fruchtbarer Baum”, LM 07/2024, S. 72, https://www.lm-online.de/50454
- LLM-Visualisierung: https://bbycroft.net/llm







