Echtzeitfähige Linux-Systeme: Eine Beispielumsetzung anhand des Raspberry Pi's

Mehr
5 Jahre 1 Monat her - 4 Jahre 10 Monate her #31 von Rainer Poisel
Kurzfassung

Dieser Artikel beschreibt die erforderlichen Schritte, um ein Linux-System echtzeitfähig zu machen. Neben einer allgemeinen Einführung in das Thema wird eine beispielhafte Umsetzung anhand des Raspberry Pi's erläutert.

Einführung

Durch die Medien wurde in der Vergangenheit oftmals ein falsches Bild vom Thema "Echtzeitsysteme" vermittelt. So geht es etwa nicht darum allgemeine Leistungsfähigkeit von Computersystemen zu steigern oder gar die Antwortzeit auf Null zu reduzieren. Vielmehr will erreicht werden, dass das Antwortzeitverhalten von Computersystemen vorhersehbar wird und dieses sich, um es in anderen Worten auszudrücken, innerhalb festgelegter Grenzen bewegt.

Steven Rostedt erklärt die Zusammenhänge in einem Interview ausführlicher. Resümierend lässt sich festhalten, dass man sich als Entwickler darüber im Klaren sein sollte, ob tatsächlich Echtzeitverhalten für das aktuelle Szenario notwendig ist. Das Antwortzeitverhalten von echtzeitfähigen Linuxsystemen lässt sich momentan nicht mathematisch beweisen. Weiters erläutert Rostedt, dass der beste Einstieg in die Materie das Anwenden des PREEMPT_RT-Patches ist. Diesem Ratschlag werden wir in den folgenden Kapiteln folge leisten.

Mit vorhersehbarer Verzögerung: Echtzeit im Linux-Kernel

Der Vorteil des PREEMPT_RT-Patches gegenüber den anderen Echtzeitimplementierungen, wie z. B. Xenomai oder RTAI bzw. RTLinux, liegt in der Weiterverwendbarkeit bereits vorhandener, bekannter Betriebssystemmechanismen. Voraussetzung für ein echtzeitfähiges System ist also ein entsprechender Kernel. Ein für den Raspberry Pi angepasstes Quellenverzeichnis kann von der Github-Projektseite bezogen werden. Achten Sie darauf, dass genuegend Speicherplatz für das Kompilieren des Kernels (ca. 1.5 - 2 GB) vorhanden ist.
git clone --depth=1 https://github.com/raspberrypi/linux.git

Grundlegende Anleitungen zur (Cross-)Kompilierung von Raspberry Pi Linux-Kerneln bieten Building and Deploying Raspberry PI Kernel und Kernel buildling . Diesen Anleitungen kann auch entnommen werden, wie man zu einer funktionierenden Toolchain kommt. Diese befindet sich am System des Authors im Verzeichnis /usr/local/toolchains/gcc-linaro-arm-linux-gnueabihf-raspbian-x64/bin.

Nach einem Wechsel in das linux-Verzeichnis kann der PREEMPT_RT-Patch angewandt werden. Wichtig ist in diesem Zusammenhang den zum Kernel passenden Patch zu verwenden. Den aktuell passenden bezieht man von der Homepage des Linux-Kernels .

Vor dem eigentlichen Anwenden empfiehlt es sich die Anwendbarkeit zu überprüfen. Dies gelingt mit der "--dry-run"-Option:
xcat patch-3.12.19-rt30.patch.xz | patch -p 1 --dry-run

Im günstigsten Fall wird das Kommando ohne Fehlermeldungen ausgeführt. Im oben angeführten Beispiel konnte ein Makefile nicht erfolgreich gepatcht werden, was jedoch durch Handarbeit mit einem Texteditor einfach zu korrigieren war. Der tatsächliche Patch-Vorgang wird durch das Weglassen der Option "--dry-run" erzielt.

Eine funktionierende Standard-Konfiguration wird mit folgendem Kommando erstellt:
ARCH=arm CROSS_COMPILE=/usr/local/toolchains/gcc-linaro-arm-linux-gnueabihf-raspbian-x64/bin/arm-linux-gnueabihf- make bcmrpi_defconfig

Anschließend können die restlichen erforderlichen Einstellungen mit folgendem Kommando gemacht werden:
ARCH=arm CROSS_COMPILE=/usr/local/toolchains/gcc-linaro-arm-linux-gnueabihf-raspbian-x64/bin/arm-linux-gnueabihf- make xconfig

Hier eine Zusammenfassung:
CONFIG_PREEMPT_RT_FULL=y
CONFIG_HIGH_RES_TIMERS=y

Weiters ist es wichtig alle Energiespeicheroptionen zu deaktivieren. Typische Schlüsselwörter sind in diesem zusammenhang "APM" (Advanced Power Management) und "ACPI" (Advanced Configuration and Power Interface).

Der eigentliche Übersetzungsvorgang wird anschließend mit folgender Befehlszeile in Gang gesetzt:
ARCH=arm CROSS_COMPILE=/usr/local/toolchains/gcc-linaro-arm-linux-gnueabihf-raspbian-x64/bin/arm-linux-gnueabihf- make -j <Anzahl-CPU-Kerne + 1>

Das Übersetzen nimmt einige Zeit in Anspruch. In der Zwischenzeit kann ein abgespecktes System von linuxsystems.it bezogen werden. Dieses dient als Ausgangsimage und wird im Folgenden an den Einsatz als Echtzeitsystem angepasst. Nach dem Entzippen kann das Image per "dd" auf eine SD-Karte passender Grüße übertragen werden (bitte darauf acnten, die richtige Gerätedatei, hier /dev/sdb, zu verwenden!):
dd if=raspbian_wheezy_20130923.img of=/dev/sdb

Nach Beendigung des Kernel-Übersetzungsvorganges befindet sich das für den Echtzeiteinsatz benötigte Resultat im Kernel-Quellverzeichnis unter arch/arm/boot/zImage und kann nach dem Mount-Vorgang auf die erste Partition auf der SD-Karte mittels "cp"-Kommando übertragen werden:
mount /dev/sdb1 /mnt/temp
cp arch/arm/boot/zImage /mnt/temp/kernel-rt.img

Bei der Gelegenheit kann gleich der Bootloader angepasst werden, sodass dieser beim nächsten Neustart des Raspberry Pi's bereits mit dem Realtime-Kernel startet. Dazu muss in der "config.txt"-Datei die "kernel="-Zeile angepasst werden, sodass auf das neue Image verwiesen wird: "kernel=kernel-rt.img". Sollte die Zeile fehlen, dann muss diese am besten gleich am Beginn der Datei eingefügt werden. Weitere mögliche Optionen des Bootloaders sind im eLinux-Wiki dokumentiert. Weiters sollten dem Linux-Kernel laut RT_PREEMPT-HowTo die Option "lapic" und laut Raspberry Pi Forum die Option "sdhci_bcm2708.enable_llm=0" hinzugefügt werden. Dies kann in der Datei "cmdline.txt" in der ersten Partition auf der SD-Karte eingestellt werden.

Zum Abschluss werden noch Kernel-Module übersetzt bzw. zusammengestellt und auf die SD-Karte übertragen (vorher die erste Partition unmounten!). Mit Hilfe der folgenen Kommandos wird dies bewerkstelligt:
mount /dev/sdb2 /mnt/temp
ARCH=arm CROSS_COMPILE=/usr/local/toolchains/gcc-linaro-arm-linux-gnueabihf-raspbian-x64/bin/arm-linux-gnueabihf- INSTALL_MOD_PATH=/tmp/modules.rt make modules_install
cp -rp /tmp/modules.rt/lib/* /mnt/temp/lib

Nach dem Vornehmen der anderen gewünschten Optionen (z. B. IP-Adresse, Benutzeroptionen wie Passwörter, usw.) direkt auf der SD-Karte stehen nach einem Start des Raspberry's mit unserem prepariertem Image den ersten Gehversuchen mit unserem Echtzeitsystem nicht's mehr im Wege.

Erste echtzeitfähige Gehversuche

Programme, die die Echtzeitfähigkeit des Linux-Kernels demonstrieren gibt es mehrere:

Und ein erster Testlauf zeigt vielversprechende Ergebnisse:

Testlauf ohne Echtzeiterweiterungen:
root@raspberry-pi:/tmp# ./cyclictest -p95 -n
# /dev/cpu_dma_latency set to 0us
policy: fifo: loadavg: 0.37 0.26 0.14 1/66 2132              

T: 0 ( 2123) P:95 I:1000 C:  25495 Min:     15 Act:   40 Avg:   79 Max:    2008
root@raspberry-pi:/tmp# ./cycle-time 
Count: 13241 Min: 0 Max: 2982 Avg: 77.986632

Sämtliche Zeiten sind in µs (Mikrosekunden) angegeben. Beim cyclictest betrug die schlechteste Antwortzeit 2ms, beim cycle-time Versuch sogar fast 3ms.

Testlauf mit Echtzeiterweiterungen:
root@raspberry-pi:/tmp# ./cyclictest -n
# /dev/cpu_dma_latency set to 0us
policy: other/other: loadavg: 0.26 0.14 0.16 1/82 2294          

T: 0 ( 2294) P: 0 I:1000 C:    876 Min:     48 Act:   95 Avg:  157 Max:    4291
root@raspberry-pi:/tmp# ./cyclictest -n -p95
# /dev/cpu_dma_latency set to 0us
policy: fifo: loadavg: 0.24 0.14 0.16 1/82 2296          

T: 0 ( 2296) P:95 I:1000 C:   1622 Min:     15 Act:   37 Avg:   29 Max:     110

root@raspberry-pi:/tmp# ./cycle-time 
Count: 10269 Min: 0 Max: -33 Avg: 5.036907
root@raspberry-pi:/tmp# ./cycle-time 
Count: 15842 Min: 0 Max: 40 Avg: 4.552203                
root@raspberry-pi:/tmp# ./cycle-time 
Count: 23567 Min: 0 Max: -28 Avg: 4.946960

Nach mehreren Testläufen mit den Echtzeiterweiterungen lässt sich festhalten, dass die schlechtesten Antwortzeiten im Bereich um die 100 µs betragen. Wesentlich zum Ergebnis trägt hierbei die Prozess-Priorität bei (siehe Ergebnis 4291 µs). Um so höher deren Wert, umso besser das Antwortzeitverhalten.

Im Rahmen der Testläufe wurde noch nicht untersucht, wie gut sich ein Programm, das mehrere Threads parallel ausführt, im Echtzeiteinsatz verhält. Dies wird Bestandteil der nächsten Teststellungen.
Letzte Änderung: 4 Jahre 10 Monate her von Rainer Poisel. Begründung: Some links were broken or expired
Folgende Benutzer bedankten sich: Karsten Hoffmann, Goltz

Bitte Anmelden oder Registrieren um der Konversation beizutreten.

  • Karsten Hoffmann
  • Besucher
  • Besucher
4 Jahre 8 Monate her - 4 Jahre 8 Monate her #65 von Karsten Hoffmann
Hallo, guter Artikel, hab ich gleich mal nachgemacht.
Im aktuellen RT-Patch finden sich dann allerdings 2 Stellen an denen das nicht passt.
1. Makefile in Drivers/misc, war einfach zu beheben
2. fs/dcache.c :Nach dem Patchen in Zeile 549 cpu_relax(); durch cpu_chill(); ersetzt
funktioniert, Danke

Ich sollte vielleicht erwähnen, dass es ich um den RT-Patch 3.12.31-rt45 handelt, beides (Linux und patch) in der Version vom 11.11.2014, und nein ... das ist kein Karnevalsscherz.
Letzte Änderung: 4 Jahre 8 Monate her von Karsten Hoffmann.

Bitte Anmelden oder Registrieren um der Konversation beizutreten.

logi.cals Österreich

Adresse

Europaplatz 7/1,
3100 St. Pölten

logi.cals Deutschland

Adresse

Postfach 1306,
40738 Langenfeld

Benutzer

Registrieren
© 1987 - 2019 logi.cals GmbH