Skip to content
Zurück zum Blog
· 6 Min. Lesezeit

Echtzeit mit Linux: was PREEMPT_RT leistet – und was nicht

Determinismus statt Tempo: wie PREEMPT_RT Linux echtzeitfähig macht, wie Sie Latenzen mit cyclictest belastbar messen und welche System- und Anwendungsfehler jede Konfiguration wieder zunichtemachen.

Schichtdiagramm der Latenzquellen eines Echtzeit-Linux-Systems: Hardware mit Frequenzskalierung und Firmware-Unterbrechungen, Kernel mit Preemption-Modell und Interrupt-Threads, Systemkonfiguration mit CPU-Isolation und Interrupt-Zuordnung sowie die Anwendung mit Scheduling-Klasse, gesperrtem Speicher und allokationsfreiem Regelpfad.

Kurz gesagt: Echtzeit bedeutet Vorhersagbarkeit, nicht Geschwindigkeit. Ein System ist echtzeitfähig, wenn es eine Frist zuverlässig einhält – auch im ungünstigsten Fall. PREEMPT_RT macht den Linux-Kernel dafür geeignet, indem es fast den gesamten Kernel unterbrechbar macht. Damit ist die halbe Arbeit getan: Die andere Hälfte liegt in der Systemkonfiguration und in der Anwendung, und dort werden die meisten mühsam gewonnenen Mikrosekunden wieder verspielt.

Determinismus ist nicht Tempo

Die häufigste Verwechslung im Gespräch über Echtzeit betrifft den Durchsatz. Ein Standardkernel ist auf mittleren Durchsatz optimiert: Er darf gelegentlich lange brauchen, solange er insgesamt viel schafft. Ein Echtzeitsystem dreht das um. Es interessiert sich für den schlechtesten Fall – für die Frage, wie spät eine Reaktion höchstens kommt.

Entsprechend ist der relevante Messwert nie der Mittelwert. Ein Regler, der 999.999 Zyklen in 50 Mikrosekunden bedient und im millionsten Zyklus 8 Millisekunden braucht, hat eine hervorragende Durchschnittslatenz und ist trotzdem unbrauchbar, wenn seine Frist bei 200 Mikrosekunden liegt. Aus dieser Perspektive folgt der zentrale Tausch: Determinismus kostet Durchsatz. Wer beides maximal will, bekommt keines von beidem.

Was PREEMPT_RT technisch verändert

Das RT-Projekt hat den Kernel über zwei Jahrzehnte hinweg an den Stellen umgebaut, an denen er nicht unterbrechbar war. Mit Linux 6.12 sind die letzten Kernbestandteile in den Hauptzweig gewandert – PREEMPT_RT ist damit keine dauerhaft mitzuführende Patch-Serie mehr, sondern eine Konfigurationsoption. Vier Änderungen tragen den Effekt:

Threaded Interrupts. Interrupt-Behandlung läuft weitgehend in normalen Kernel-Threads statt im harten Interrupt-Kontext. Damit werden Interrupt-Handler planbar – und ein Handler, der zu einem unwichtigen Gerät gehört, kann einen zeitkritischen Task nicht mehr beliebig lange blockieren.

Schlafende Sperren. Die meisten Spinlocks werden zu Mutexen, die schlafen können. Ein Task, der eine Sperre nicht bekommt, blockiert damit nicht mehr die CPU, sondern gibt sie ab.

Priority Inheritance. Hält ein niedrig priorisierter Task eine Sperre, die ein hoch priorisierter braucht, erbt er dessen Priorität, bis er sie freigibt. Das entschärft die klassische Prioritätsinversion, bei der ein mittelpriorisierter Task die eigentlich wichtige Arbeit aushungert.

Hochauflösende Timer. Zeitgesteuerte Aufgaben werden nicht mehr an den Systemtakt gebunden, sondern feiner aufgelöst geweckt.

Das Ergebnis ist ein Kernel, der auf geeigneter Hardware und mit sauberer Konfiguration Reaktionszeiten im Bereich einiger zehn bis einiger hundert Mikrosekunden einhält. Die Spanne ist Absicht: Sie hängt stärker von der Plattform ab als vom Kernel.

Die Preemption-Modelle im Überblick

ModellVerhaltenTypischer Einsatz
PREEMPT_NONEKernel wird nicht unterbrochenServer, Batch-Verarbeitung, maximaler Durchsatz
PREEMPT_VOLUNTARYDefinierte UnterbrechungspunkteAllgemeine Systeme mit etwas besserer Reaktion
PREEMPTKernel weitgehend unterbrechbarDesktop, Multimedia, viele Embedded-Geräte
PREEMPT_RTNahezu vollständig unterbrechbar, threaded IRQsSteuerung, Regelung, Motion Control, Audio

Der Sprung von PREEMPT auf PREEMPT_RT ist kleiner, als viele erwarten. Für Geräte, deren Fristen im Bereich mehrerer Millisekunden liegen, reicht das Modell PREEMPT oft aus – ein lohnender erster Test, bevor man den vollen RT-Weg einschlägt.

Messen statt glauben

Latenzangaben ohne Messbedingungen sind wertlos. Das Standardwerkzeug ist cyclictest aus den rt-tests: Es weckt einen Task in festem Intervall und misst, wie stark der tatsächliche Weckzeitpunkt vom geplanten abweicht.

# Ein RT-Task auf einem isolierten Kern, zehn Minuten, mit Histogramm
cyclictest -m -S -p 80 -i 200 -h 400 -D 10m

Zwei Regeln entscheiden über die Aussagekraft. Erstens: unter Last messen. Ein Leerlaufsystem liefert schöne Zahlen, die nichts über den Betrieb sagen. Erzeugen Sie parallel die Last, die im Feld auftritt – Netzwerkverkehr, Schreibzugriffe auf den Flash-Speicher, Grafikausgabe, Zugriffe über den Feldbus. Zweitens: lange genug messen. Seltene Ausreißer sind genau die, die im Feld zuschlagen; Läufe über Stunden oder Tage sind üblich. Interessant ist immer die maximale Abweichung, nicht der Durchschnitt.

Zeigt sich ein Ausreißer, hilft ftrace weiter: Der Kernel kann aufzeichnen, wer die Verzögerung verursacht hat. Weil solche Läufe zur Regressionsfrage werden, sobald das Produkt in Pflege geht, gehören sie in die automatisierte Verifikation – wir lassen sie auf echter Hardware laufen, wie im Beitrag zum Hardware-in-the-Loop-Testing beschrieben.

Das System um den Kernel herum

Ein RT-Kernel allein garantiert nichts. Diese Punkte entscheiden in der Praxis über das Ergebnis:

  • CPU-Isolation. Ein oder mehrere Kerne werden dem Scheduler entzogen (isolcpus) und von periodischen Aufgaben befreit (nohz_full, rcu_nocbs), damit dort ausschließlich die zeitkritische Arbeit läuft.
  • Interrupt-Zuordnung. Interrupts nicht benötigter Geräte werden von den isolierten Kernen weggeleitet, die des zeitkritischen Geräts gezielt dorthin.
  • Frequenz- und Energieverwaltung. Dynamische Taktung und tiefe Schlafzustände sind eine der häufigsten Latenzquellen: Das Aufwachen aus einem tiefen C-State kostet Zeit, die im ungünstigsten Fall direkt in die Reaktionszeit eingeht.
  • Firmware-Unterbrechungen. Auf x86-Plattformen können System Management Interrupts den Kernel unbemerkt anhalten. Sie sind vom Betriebssystem aus nicht kontrollierbar, weshalb die Plattformauswahl selbst eine Echtzeitentscheidung ist.
  • Speicher. Ein Seitenfehler im Regelpfad kostet mehr als alles, was der Scheduler je einspart.

Die Anwendung entscheidet mit

Auch die beste Konfiguration hilft nicht gegen eine Anwendung, die sich nicht an Echtzeitregeln hält. Vier Punkte tragen den größten Teil:

// Speicher sperren, damit im Regelpfad keine Seitenfehler auftreten
mlockall(MCL_CURRENT | MCL_FUTURE);

// Echtzeit-Scheduling mit bewusst gewählter Priorität
struct sched_param param = { .sched_priority = 80 };
pthread_setschedparam(thread, SCHED_FIFO, &param);

Erstens die Scheduling-Klasse: Ohne SCHED_FIFO, SCHED_RR oder SCHED_DEADLINE bleibt der Task ein gewöhnlicher Prozess und konkurriert mit allem anderen. Zweitens die Prioritätswahl – sie muss unterhalb der wichtigen Kernel-Threads liegen, sonst hungert die Anwendung genau die Interrupt-Threads aus, auf die sie angewiesen ist. Drittens kein dynamischer Speicher im heißen Pfad: Allokation kann blockieren, weshalb Puffer vorab reserviert werden. Die dafür nützlichen Sprachmittel haben wir im Beitrag zu modernem C++ für Embedded-Systeme beschrieben. Viertens keine blockierenden Aufrufe im Regelzyklus – kein Logging auf ein volles Dateisystem, keine Netzwerkoperation ohne Zeitbegrenzung.

Wann Linux die falsche Antwort ist

Es gibt Anforderungen, bei denen auch ein perfekt konfiguriertes RT-Linux nicht das richtige Werkzeug ist: Fristen im einstelligen Mikrosekundenbereich, streng zyklische Regelung im hohen Kilohertz-Bereich oder Nachweispflichten, die eine überschaubare, zertifizierbare Codebasis verlangen.

Die übliche Antwort darauf ist keine Entweder-oder-Entscheidung, sondern eine Aufteilung. Viele moderne SoCs bringen neben den Applikationskernen einen Mikrocontroller-Kern mit, der die harte Regelschleife übernimmt, während Linux Bedienoberfläche, Netzwerk und Datenhaltung bedient. Diese Arbeitsteilung liefert beides – harte Fristen dort, wo sie gebraucht werden, und ein vollwertiges Betriebssystem für alles andere. Welche Aufteilung für ein Produkt sinnvoll ist, klären wir regelmäßig in der technischen Beratung.

Der Weg ins eigene Produkt

In einem Yocto-basierten Aufbau ist der RT-Kernel meist eine Frage der Kernel-Auswahl im BSP – viele Layer liefern eine RT-Variante mit, sodass Rezepte und Konfiguration erhalten bleiben. Der Aufwand liegt selten im Umschalten, sondern in der anschließenden Validierung: Treiber, die im Standardkernel unauffällig waren, können unter RT auffallen, weil sie zu lange in nicht unterbrechbaren Abschnitten verweilen. Genau dafür ist die Messung unter Last da. Wie wir BSPs schneiden und pflegen, steht unter Yocto BSP & Distributionen und Embedded Linux.

Fazit

PREEMPT_RT ist ein ausgereiftes Werkzeug, das Linux für einen großen Teil industrieller Steuerungsaufgaben tauglich macht – seit der Aufnahme in den Hauptzweig ohne den Ballast einer externen Patch-Serie. Es ersetzt aber keine Systemarbeit: Isolation, Interrupt-Zuordnung, Energieverwaltung und eine disziplinierte Anwendung entscheiden am Ende über die Zahlen. Messen Sie auf der Zielhardware, unter realistischer Last und lange genug, und richten Sie sich am Maximum aus statt am Mittelwert. Wenn Sie einschätzen lassen möchten, ob Ihre Fristen mit Linux erreichbar sind oder eine geteilte Architektur die bessere Wahl ist, sprechen Sie uns an.

Häufige Fragen

Ist ein Linux mit PREEMPT_RT ein Echtzeitbetriebssystem?
Es ist ein Betriebssystem, das für viele Steuerungsaufgaben ausreichend deterministisch wird. Ob das genügt, entscheidet Ihre Deadline: Bei Anforderungen im Bereich weniger Mikrosekunden oder bei harter Zertifizierungspflicht ist ein dedizierter Mikrocontroller neben dem Applikationsprozessor die ehrlichere Antwort. Für Zykluszeiten im Bereich einiger hundert Mikrosekunden bis Millisekunden ist Linux mit PREEMPT_RT gut geeignet.
Kostet PREEMPT_RT Rechenleistung?
Ja. Threaded Interrupts, feinere Sperren und mehr Kontextwechsel senken den Gesamtdurchsatz spürbar, während sie die Streuung der Reaktionszeiten drücken. Das ist genau der Tausch, den man eingeht: Der schlechteste Fall wird besser, der Durchschnitt schlechter. Wo Durchsatz zählt, ist ein Standardkernel die bessere Wahl.
Welche Latenz können wir erwarten?
Das hängt an der Hardware, nicht am Kernel allein. Aussagekräftig ist nur eine Messung auf dem Zielsystem unter realistischer Last – typischerweise über Stunden mit cyclictest, parallel zu Netzwerk-, Speicher- und Grafiklast. Der interessante Wert ist das gemessene Maximum, nicht der Durchschnitt.

Alexander Nassian

Geschäftsführer, bitshift dynamics

Entwickelt mit seinem Team hardwarenahe Software für Embedded-Produkte – C++, Qt/QML, Embedded Linux und das Yocto Project. bitshift dynamics arbeitet seit 2005 in diesem Feld.

Verwandte Beiträge

· 6 Min. Lesezeit

Device Tree in der Praxis: Hardware beschreiben, statt Treiber zu raten

Wie der Device Tree in Embedded-Linux-Projekten wirklich funktioniert: compatible-Matching, pinctrl und Clocks, Overlays für Gerätevarianten und die Debug-Rezepte, mit denen sich Bring-up-Probleme eingrenzen lassen.

  • Embedded Linux
  • Device Tree
  • Kernel
Weiterlesen
· 6 Min. Lesezeit

Boot-Zeit von Embedded Linux optimieren: messen, bevor Sie schrauben

Von Power-on bis zum ersten Bild: wie Sie die Boot-Zeit eines Embedded-Linux-Geräts belastbar messen und in Bootloader, Kernel und User-Space die Hebel finden, die tatsächlich Sekunden bringen.

  • Embedded Linux
  • Boot-Zeit
  • Performance
Weiterlesen

Steht bei Ihnen eine ähnliche Aufgabe an?

Wir begleiten Embedded-Teams genau bei solchen Fragestellungen – von der Architekturentscheidung bis zur Serienreife. Schildern Sie uns kurz Ihr Vorhaben.

Projekt anfragen