Linux in Mission Critical Systems einsetzen? Kein Problem: Ein Raspberry Pi mit PREEMPT_RT-Patch zeigt eindrucksvoll die Realzeitfähigkeiten des Linux-Kernels auf.
Spätestens seit die NASA ihre Astronautinnen, Astronauten und Fracht der Crew-Dragon-Kapsel und der Falcon-9-Rakete der Firma SpaceX anvertraut, ist klar: Linux ist ready for mission critical systems. Auf Reddit hat sich das SpaceX-Software-Team unter der Rubrik AMA (ask me anything [1]) im Juni 2020 den Fragen Neugieriger gestellt und bereitwillig geantwortet (Abbildung 1). Die Entwickler berichteten von damals bereits über 30 000 Linux-Knoten im Orbit, die in Starlink-Satelliten verbaut sind, und von über 180 Jahren Linux-Laufzeit im Weltraum. Am Kernel selbst gibt es unabhängig von der Entwicklung eigener Gerätetreiber kaum Veränderungen. Das SpaceX-Team hat lediglich den PREEMPT_RT-Patch auf die Kernel-Quellen losgelassen, um ein deterministischeres Realzeitverhalten zu erreichen. Der Rest liege in der Applikation, heißt es.
Schon seit Jahren krempelt unter anderem der deutsche Entwickler Thomas Gleixner erfolgreich den Linux-Kernel in Richtung Realzeit um und erstellt ein Set von Patches, das dem Betriebssystemkern mehr Realzeitverhalten einhaucht: PREEMPT_RT. Zwischenzeitlich hat Chefarchitekt Linus Torvalds große Teile der Patches als fixen Kernel-Bestandteil seinem Quellcodearchiv einverleibt, den Standard-Kernel um neue Realzeitmechanismen erweitert und das Patch-Set damit immer weiter miniaturisiert. Es ist nur eine Frage der Zeit, bis der Kernel die letzten Patches aufgesaugt haben wird.
Realzeitsysteme zeichnen sich dadurch aus, dass sie neben den funktionalen auch zeitlichen Anforderungen genügen. Sie reagieren auf Ereignisse innerhalb eines klar definierten Zeitfensters (Abbildung 2), weil die Laufzeit von Kernel und Applikation leidlich vorherzusehen und deterministisch ist, sich also mit einer Oberschranke angeben lässt. Die Größe des Zeitfensters nennen Profis Reaktionszeit, während alles, was das eigentliche Bearbeiten des Ereignisses verzögert, die Latenzzeit darstellt.
Da die Reaktionszeit von der jeweiligen Aufgabenstellung (Laufzeit der Algorithmen) abhängt, ist die Latenzzeit eine der ausschlaggebenden Größen, um ein Realzeitsystem zu betrachten und zu bewerten. Je kleiner die Latenzzeit auch bei größter Auslastung und unter allen Umständen ausfällt, desto besser ist das System – oder, um es neutral zu sagen: desto mehr Einsatzmöglichkeiten gibt es.
Die Ursachen für Latenzzeiten sind vielfältiger Natur. Ist der Betriebssystemkern mit etwas sehr Wichtigem beschäftigt, lässt er sich dabei nicht unterbrechen. In den Anfangstagen von Linux, als das Zeitverhalten nur unter dem Gesichtspunkt Durchsatz relevant war und Latenzzeiten für Standardbetriebssysteme keine Rolle spielten, ging man auf Nummer sicher, indem man generell Unterbrechungen unterband. Schließlich gehören Unterbrechungen zu den Hauptübeln für Fehlverhalten von Softwaresystemen.
Latenzzeitkiller
Die Leistung der Entwicklerinnen und Entwickler beim Erstellen und Pflegen der RT-Patches besteht entsprechend darin, die nicht unterbrechbaren Bereiche zu identifizieren und unterbrechbar (preemptible) umzubauen. Daher stammt auch der Name des Patch-Sets: PREEMPT_RT. Unterbrechbarkeit ist aber nur eine Seite der Medaille und des Patch-Sets. Daneben sind Mechanismen wichtig, um beispielsweise gezielt auf die Abarbeitungsreihenfolge von Tasks (das Scheduling) Einfluss zu nehmen.
Das Scheduling auf Basis von Prioritäten ist für ein Realzeitsystem zwingend notwendig und ein Deadline-Scheduling, bei dem die Auswahl der anschließend zu bearbeitenden Task auf Basis der Reaktionszeit stattfindet, wünschenswert. Damit sich Interrupts priorisieren lassen, lagern Realzeitsysteme zeitintensive Teile der Interrupt-Service-Routinen in Kernel-Threads aus. Hier sprechen Expertinnen und Experten von Threaded Interrupts.
Die Prioritätsgeschichte in Kombination mit dem Schutz kritischer Abschnitte wiederum führt zur Prioritätsinversion, der man die Prioritätsvererbung entgegensetzt. Die Tabelle “PREEMPT_RT” zeigt weitere Techniken, die Linux im Rahmen der PREEMPT_RT-Entwicklung eingebaut hat.
|
Kurzbeschreibung |
Realzeit-Technologien |
|---|---|
|
Preemption |
Kernel-Code lässt sich jederzeit unterbrechen. |
|
High Resolution Timer |
Zeitfunktionen mit hoher Auflösung. |
|
Threaded Interrupts |
Auf Applikationsebene priorisierbare Interrupts. |
|
Prioritätsvererbung |
Auf Betriebsmittel wartende Tasks vererben ihre (hohe) Priorität an Betriebsmittel nutzende Tasks. |
|
Tickless Betrieb |
Der Kernel wird nicht periodisch aktiv, sondern bedarfsgesteuert. |
|
Earliest Deadline First Scheduler |
Auswahl zu bearbeitender Tasks auf Basis der Reaktionszeit. |
|
Realzeit-Locks |
Elemente zum Schutz kritischer Abschnitte. |
|
Memory Locking |
Verhindern des zu Latenzzeiten führenden Auslagerns von Speicherseiten. |
Selbst machen
Genug der Vorrede, hinein in die Praxis. Die Wirkungsweise eines PREEMPT_RT-Linux lässt sich sehr eindrucksvoll mit etwas Handarbeit verdeutlichen. Um unsere Arbeitsmaschine nicht modifizieren zu müssen, wählen wir einen Raspberry Pi 4 als Versuchsobjekt, generieren einen (gepatchten) Kernel und installieren sowie booten ihn zusammen mit einigen Testprogrammen. Den zum jeweiligen Kernel passenden PREEMPT_RT-Patch [2] finden Sie ebenso wie bereits gepatchte [3] Kernel-Quellcodes [4] in den Repositories von Kernel.org.
Listing 1 zeigt die Kommandos zum Cross-Kompilieren eines Linux-Kernels für den Raspberry Pi auf einem PC. Hintergrundinfos dazu finden Sie auf den Seiten der Raspberry Pi Foundation [5]. Zunächst installieren Sie die Tools zum Cross-Kompilieren, darauf folgt das Herunterladen des aktuellen, stabilen Linux-Kernels und der Patch-Datei, die schließlich den Kernel auf volle Realzeit umbaut.
Aus Geschwindigkeitsgründen empfiehlt es sich, den Raspberry-Pi-Kernel auf dem PC zu erzeugen. Dazu setzen Sie die Umgebungsvariablen KERNEL, ARCH und CROSS_COMPILE. Für das zu erreichende Realzeitverhalten ist die Konfiguration entscheidend, bei der make menuconfig den PREEMPT_RT-Patch erst aktiviert. Die Einstellungen finden Sie in der Kernel-Konfiguration unter dem Oberpunkt General Setup. Sofern das nicht schon als Vorgabe gesetzt ist, wählen Sie zunächst den Modus für expert users aus.
Preemption-Modelle
Grundsätzlich stehen vier Preemption-Modell zur Wahl. Bei CONFIG_PREEMPT_NONE handelt es sich um das traditionelle Verhalten eines Unix-Kernels. Der Kernel-Code (Interrupt-Service-Routinen, Systemaufrufe) wird nicht unterbrochen. Diese Konfiguration garantiert den bestmöglichen Durchsatz, da es zu wenigen Kontextwechseln kommt. Daraus resultiert eine gute Ausnutzung von CPU und Caches. Diese Einstellung ist am besten für Server geeignet.








