Hallo Kernel – Meine ersten Schritte mit Embedded Linux

Diesmal tauche ich in Embedded Linux und die Entwicklung von Kernel-Treibern ein – ein Gebiet, das sowohl einschüchternd als auch unglaublich spannend ist. Wenn Staffel 1 vom Erlernen der Embedded-Programmierung mit Mikrocontrollern handelte, geht es jetzt eine Ebene tiefer – darum, zu verstehen, wie Linux selbst mit Geräten kommuniziert.
Hinweis: Der Podcast ist ausschließlich auf Englisch verfügbar.
Warum der Kernel?
Ich habe schon immer gern mit Mikrocontrollern experimentiert – aber mit der Zeit fragte ich mich, wie viel von dieser Low-Level-Kontrolle eigentlich verloren geht, sobald man auf ein vollwertiges Linux-System wechselt.
Bei Mikrocontrollern steuert man alles direkt: Register, Timing, Speicher. Unter Linux existiert eine komplette Abstraktionsschicht – und genau die wollte ich verstehen. Hier setzt die Kernel-Entwicklung an. Der Kernel ist die Brücke zwischen Anwendungen und Hardware. Hier leben die Gerätetreiber, hier wird Speicher verwaltet und Systemaufrufe werden bearbeitet.
Er ist das Herz des Betriebssystems – und mit ihm zu interagieren fühlt sich an, als würde man eine neue Ebene des Verstehens freischalten.
Mein Linux-Arbeitsplatz
Anstatt Firmware für Mikrocontroller zu schreiben, arbeite ich nun an Kernel-Modulen – kleinen, ladbaren C-Programmen, die den Linux-Kernel erweitern.
Dafür habe ich mir eine eigene Entwicklungsumgebung eingerichtet:
- Ubuntu 25.04 in UTM (QEMU) auf macOS
- Eine komfortable Terminal-Umgebung mit Zsh + Oh-My-Zsh
- VS Code zum Bearbeiten und Bauen
- Kernel-Header und
build-essential
-Pakete zum Kompilieren der Module
💡 Tipp: Wer auf macOS arbeitet, kann mit UTM sehr leichtgewichtig Linux virtualisieren – komplett Open Source und erstaunlich flüssig für Kernel-Experimente.
Bevor ich Code schrieb, habe ich etwas Zeit in die Anpassung meiner Arbeitsumgebung gesteckt. Das klingt banal, aber wenn sich das Setup „eigen“ anfühlt, macht das Lernen deutlich mehr Spaß – und es ist eines dieser kleinen Rituale, die den Grundton für ein Projekt setzen.
Mein erstes „Hello Kernel“-Modul
Mein erster Meilenstein war klein, aber bedeutungsvoll: Eine „Hello Kernel“-Nachricht im System-Log erscheinen zu lassen.
Dafür brauchte es nur ein paar Zeilen C-Code:
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Stefan Herndlbauer");
MODULE_VERSION("1.0.0");
MODULE_DESCRIPTION("A simple HelloWorld module");
static int __init helloworld_init(void) {
printk(KERN_INFO "Hello World!\n");
return 0;
}
static void __exit helloworld_exit(void) {
printk(KERN_INFO "Goodbye World!\n");
}
module_init(helloworld_init);
module_exit(helloworld_exit);
- Modul-Metadaten mit Makros wie
MODULE_LICENSE
undMODULE_AUTHOR
definieren - Zwei zentrale Funktionen implementieren:
__init()
und__exit()
- Mit einem einfachen
Makefile
kompilieren - Mit
insmod
laden und das Kernel-Log perdmesg
prüfen
Als ich meine Nachricht schließlich im Kernel-Log sah, fühlte es sich anders an als jedes „Hello World“ zuvor – diesmal lief der Code im Betriebssystem selbst.
Ein seltsames, aber aufregendes Gefühl: Der eigene Code ist jetzt Teil des OS und läuft nicht nur darüber.
Was passiert, bevor Linux startet?
Beim Lernen wurde mir klar, wie viel passiert, bevor der Kernel überhaupt die Kontrolle übernimmt.
Eine faszinierende Kette von Schritten, über die man selten nachdenkt:
- ROM Bootloader – winziger Code im Prozessor
- First-stage bootloader – initialisiert RAM und Speicher
- Second-stage bootloader (z.B., U-Boot) – lädt das Kernel-Image
- Kernel initialization – mountet Dateisysteme und startet Prozesse
Dieses Wissen lässt Linux weniger wie eine „Black Box“ erscheinen – sondern wie ein elegant geschichtetes System, das über Jahrzehnte gereift ist.
Warum das für Maker wichtig ist
Für die meisten Maker-Projekte reicht ein Mikrocontroller völlig aus. Doch sobald Projekte komplexer werden – z. B. bei Robotik, Drohnen oder Computer Vision – braucht man mehr Rechenleistung und echtes Multitasking. Genau hier kommt Embedded Linux ins Spiel.
Mittlerweile gibt es ein ganzes Ökosystem von Single-Board-Computern, die Linux ausführen können: Raspberry Pi, BeagleBone, Orange Pi, Rock Pi, Radxa … alle mit eigenen Stärken.
Gemeinsam ist ihnen die Möglichkeit, direkt über Treiber mit GPIOs, Sensoren und eigener Hardware zu kommunizieren. Natürlich kann man auch Python-Bibliotheken oder User-Space-Wrapper verwenden, um Pins zu steuern – aber ich wollte die Mechanik darunter verstehen: Wie funktionieren diese Abstraktionen eigentlich?
Darum geht es in dieser Staffel:
Zu lernen, wie das Betriebssystem selbst mit der Welt außerhalb der CPU spricht.
Lernziele dieser Staffel
Dieses Projekt ist mehr als eine technische Übung – es ist eine persönliche Lernreise.
Ich möchte:
- Mein Wissen in C-Programmierung vertiefen
- Lernen, echte Kernel-Treiber zu bauen, zu debuggen und zu laden
- Cross-Compiling für Embedded-Ziele wie den Raspberry Pi erforschen
- Und vor allem – jeden Schritt offen teilen – auch die Fehler und Umwege
Es geht nicht darum, über Nacht Kernel-Entwickler zu werden – sondern darum, die Maker-Welt um eine weitere Ebene zu erweitern, eine C-Zeile nach der anderen.
Wie es weitergeht
In der nächsten Episode wechsle ich von der VM auf echte Hardware – und cross-kompiliere mein erstes Kernel-Modul für den Raspberry Pi. Dazu gehören ARM-Toolchains, Kernel-Header und das Remote-Deployment.
Wer mitmachen möchte: In den kommenden Blogposts teile ich Befehle, Konfigurationen und Fehleranalysen – wie immer dokumentiert hier und in meinem Newsletter.
📬 Willst du wöchentliche Einblicke hinter die Kulissen meiner Werkbank (Projekte, die es nicht immer in den Podcast schaffen)? Dann abonniere mein Maker’s Logbook. 👉 herndlbauer.com/pages/newsletter
Lasst uns weiter bauen, erschaffen und lernen — gemeinsam.