Linux Fast-Boot im Fahrzeug Hochfahren vor dem Fahren

Bei vielen Linux-basierten Anwendungen sind die Bootzeiten des Betriebssystems zur kritischen Messgröße ihrer Leistungsfähigkeit geworden. Obwohl Verbraucher bei Produkten wie Set-Top-Boxen und Smartphones heute Bootzeiten von 30 Sekunden akzeptieren, sind diese Wartezeiten beispielsweise bei Infotainment-Systemen im Fahrzeug ganz unmöglich.

Da Fahrzeughalter von ihren Infotainment- und Telematiksystemen immer mehr kundenorientierte Funktionen erwarten und somit die Software sowohl an Komplexität als auch an Quantität zunimmt, werden Bootzeiten tendenziell immer länger – dies kann die Industrie allerdings nicht zulassen. Die Auswahl der schnellsten Hardware ist eine Möglichkeit, die aber negative Auswirkungen auf die Kosten hat. Eine andere Alternative wäre, nach Möglichkeiten zu suchen, das Betriebssystem und die entsprechenden Ladezeiten der Anwendungen zu optimieren. Und genau dies ist der Ansatz, den die IVI-Entwickler mit Nachdruck verfolgen. Der vorliegende Artikel erläutert einige der Abläufe beim Booten eines typischen Linux-basierten Systems und blickt auf die Tools und Lösungen zur Reduzierung der Bootzeiten.

Der Fahrer erwartet eine sofortige Reaktion, wenn er das Fahrzeug mit Hilfe des Zündschlüssels oder schlüssellos startet. Diese unmittelbare Reaktion könnte in einem Startbildschirm (Splash Screen) mit Logo bestehen, der anzeigt, dass das System aktiviert wurde, während im Hintergrund die verschiedenen Bootprozesse ablaufen. Viele der kritischen Funktionen müssen direkt nach dem Zünden des Fahrzeugs zur Verfügung stehen, insbesondere die Funktionen der Fahrerassistenzsysteme (ADAS, Advanced Driver Assist Systems). Einige dieser Funktionen und mögliche Ladezeiten sind in Tabelle 1 dargestellt.

Systemfunktion erwartete Ladezeit 
CAN-Bus initialisiert 50 ms 
Splash Screen/grafische Anzeige100 ms
erstes Audiosignal1 s
rückwärtige Kamera2 s
Multimedia und Netzwerk (komplett) 4 s 
Tabelle 1: Bootzeiten im Fahrzeug variieren je nach Funktion und Erwartung des Fahrers

Fast-Boot-Prozesse

Durch sorgfältiges Strukturieren aller Komponenten des Startvorgangs bei einem Linux-basierten System lassen sich diese (und sogar noch bessere) Bootzeiten erreichen. Es gibt jedoch nicht die eine optimale Lösung. Stattdessen gilt es, eine Kombination von technischen Lösungen einzusetzen, mit deren Hilfe die Leistungsziele erreicht werden können – und dies ist aller Wahrscheinlichkeit nach ein iterativer Prozess. Die meisten Entwickler von Infotainment-Systemen beginnen mit experimentellen Entwicklerplatinen. Heutzutage sind diese üblicherweise mit Multicore-CPUs ausgestattet und werden mit kostenlosem Download von Linux-Distributionen angeboten. Eine häufig eingesetzte Hardwareplattform ist Freescales »i.MX6« mit einem Quad-Core-ARM-»Cortex A9« mit 1 GHz und einer Reihe sehr nützlicher Peripherieanschlüsse für Infotainment-Systeme wie zum Beispiel On-Board-GPU, Audio, dualer Videoausgang, USB, Massenspeicher und Netzwerkunterstützung. Bei einer nicht optimierten »Yocto Core«-Image-Anwendung mit einem 90-MByte-Dateisystem beträgt die Bootzeit von einer Class-10-MicroSD-Karte 23 s bis zum vollständigen Desktop. Obwohl dies bei vielen Anwendungen akzeptabel erscheint, ist es für den Einsatz in Infotainment-Systemen im Fahrzeug zu langsam.

Um den Vorgang zu beschleunigen, muss man sich zunächst jeden Schritt der Bootsequenz für die Embedded-Hardware und -Software ansehen. Ein typischer Ablauf ist in Bild 1 dargestellt. Der Vorgang beginnt mit dem Aufwecken der Hardware und dem Lesen der Konfigurationsschalter. Der »Hardware Reader/Loader« ist eine einfache, in den CPU-Chip eingebaute Zustandsmaschine. Sie liest die On-Board-Konfigurationsschalter und kann aus den verfügbaren einfachen Speichergeräten auswählen, wie zum Beispiel dem On-Board-SPROM oder dem ersten Block eines Flash-Speichers. Danach lädt der IBL (Initial Boot Loader) weitere Programme und Funktionen aus dem NAND- oder NOR-Speicher, was manchmal als Boot-Strapping (Urladen) bezeichnet wird. Der IBL ist üblicherweise in seiner Größe begrenzt (nur ein paar wenige NAND-Blocks); er hat aber ausreichend Kapazitäten, um einen Bootloader mit allen Funktionen, wie zum Beispiel einen ausführbaren »uboot«, in den Speicher zu laden. Dieses Dienstprogramm ist dann in der Lage, den gesamten Linux-Kernel und die benötigten Dateisysteme sowie die User-Anwendungen im On-Board-Speicher/Peripheriespeicher zu lokalisieren und zu laden. Bei Embedded Systemen sind möglicherweise nicht alle Bootsequenzen notwendig, und Shortcuts sind in einigen frühen Phasen möglich.

Obwohl das SoC möglicherweise vorab zugewiesen wurde und somit kein Raum für Änderung bleibt, gibt es dennoch einige Möglichkeiten der Hardwareoptimierung, die über das Offensichtliche wie etwa das Festlegen der maximalen Taktfrequenz hinausgehen. Das Laden aus dem NAND beziehungsweise von einer SD-Karte /einem MMC-Speicher geht schneller vonstatten als das Laden aus dem SPI oder NOR, sodass die größeren Bootprogramme in den schnelleren Speicherbereichen angesiedelt werden müssen. Wenn man Hochleistungsmassenspeichergeräte verwendet, kann man entscheidende Millisekunden bei den Ladephasen großer Dateien einsparen. Es ist daher wichtig, dass die Entscheidungen, wo Kernel und Root-File-Systeme zu speichern sind, auch mit Blick auf die tatsächlichen Dateigrößen und Hardwarezugriffszeiten auf verfügbare Speicher getroffen werden.

Optimierung des Kernels

Der Linux-Kernel wird beim Booten normalerweise vom Flash-Speicher in das RAM geladen. Der Kernel ist dabei üblicherweise in komprimierter Form gespeichert, und das Entpacken kann einige hundert Millisekunden dauern. Bei einem kleineren Kernel lohnt es sich oftmals, über eine nicht komprimierte Speicherung nachzudenken, allerdings verlängert sich dadurch die Ladezeit. Der Kernel erkennt viele der verfügbaren Gerätetreiber im System und fragt die Geräte ab, um festzustellen, welche angeschlossen sind – dies kann wertvolle Zeit kosten, wenn ein Gerät nicht angeschlossen ist oder zunächst nicht gebraucht wird. Wenn der Entwickler eine vorab konfigurierte Liste der zwingend für den Systemstart vorgeschriebenen Treiber anlegt, kann er diese Phase der Kernel-Bootzeiten reduzieren. Verzichtbare Treiber können dann als Kernel-Module später während des Prozesses geladen werden.

Standardmäßig erstellt der Kernel unter Linux mithilfe der »printk«-Befehle ein Protokoll des Bootprozesses. Diese Befehle erhöhen aber auch die Systemlast, sodass es bei Produktivsystemen zu Zeitersparnissen führen kann, die Befehle zu reduzieren oder abzuschalten. Allerdings sind sie auch für die Definition der Debug-Schritte nötig. Mithilfe der ».config« Datei des Linux-Kernels lassen sich die Elemente, die in einen neuen Kernel integriert werden, weitgehend flexibel auswählen. Geht man hier sorgfältig vor, können viele der Funktionen eingespart und der Kernel auf ein Minimum reduziert werden. Durch Änderungen an den core-init- und module-init-Dateien lässt sich bestimmen, welche Treiber und Kernelfunktionen beim Start verfügbar sind. Bei den meisten Systemen ist es jedoch die Initialisierung des Root-File-Systems und der Anwendungen, bei der die größten Einsparungen erzielt werden können. Sich lediglich auf den Kernel zu konzentrieren, ist einfach nicht genug.

Optimierung des Root-File-Systems

60 bis 80 Prozent des gesamten Bootvorgangs entfallen auf das Laden des RootFS (Root File Systems) und der entsprechenden Anwendungen. Daher lassen sich hier die größten Zeitersparnisse erzielen. In der Vergangenheit wurden »SysV«-Skripts verwendet, um die zu ladenden Prozesse und Dienste zu definieren. Heute kommt bei Linux-Systemen weitgehend »Systemd« zum Einsatz. Der Grund: Systemd vermeidet Forks und zeitaufwendiges Abfragen anderer Prozesse und ist daher zeiteffizienter als die SysV-Lösungen. Ein Großteil der Zeit, die zur Anwendungsinitialisierung notwendig ist, entfällt bei dynamischen Bibliotheken auf das Auflösen und Integrieren von Symbolen. Durch »Prelinking« lässt sich diese Zeit einsparen. Dabei wird jeder zu initialisierenden Anwendung vorab eine Adresse zugewiesen, sodass die Zeiten für das Suchen und Auffinden entfallen.

Die Verringerung der Anzahl von Tools und Befehlen im RootFS kann ebenfalls zu geringeren Softwareladezeiten führen – die »Linux BusyBox« ist bei eingebetteten Systemen weit verbreitet und enthält die wichtigsten Tools in einem Paket. Im Produktivsystem lassen sich viele Werkzeuge und Befehle entfernen, um Platz zu sparen und Ladezeiten zu reduzieren. Der »init«-Prozess, der bestimmt, welche Dienste und Prozesse beim Booten geladen werden, kann komplett an die eigenen Bedürfnisse angepasst werden, um beispielsweise Skripts und Prozesse parallel statt sequenziell zu starten. Wo systemeigene Codes statt Skripts zum Einsatz kommen können, lässt sich ebenfalls Zeit einsparen.

Auch bei den Anwendungen selbst wird die Softwareladezeit reduziert, wenn diese Anwendungen so klein wie möglich gehalten werden. Sofern Multicore-SoC-Hardware verfügbar ist, besteht die Möglichkeit, Anwendungen zu verteilen und auf separaten Kernen zu betreiben. Dies kann dazu führen, dass das Laden von Diensten wie WLAN und Bluetooth auf einen späteren Zeitpunkt in der Bootsequenz verschoben wird und zunächst solche Audio-/Grafikdienste und Anwendungen bereitgestellt werden, die notwendig sind, um dem Anwender sofortige Rückmeldungen zu geben.

Fortschritte messen

Bei der Optimierung der Bootzeiten und der Messung der Vorher-/Nachher-Effekte ist ein wissenschaftlicher Ansatz sinnvoll. Linux bietet eine Reihe von hilfreichen Diagnosetools zum Einrichten und Optimieren des Bootprozesses. Einige dieser Werkzeuge sind in Tabelle 2 aufgeführt.

Befehl Funktion Anmerkung 
printk Debuggen von Kernelereigniszeiten Kann auch mit printk.time in der Kernelbefehlszeile verwendet werden. 
ftraceLatenz- und Leistungsanalyse des KernelsBraucht etwas Zeit, um sich damit vertraut zu machen
bootchartStellt den Ablauf der Ereignisse beim Start darEinfach zu installieren und anzuwenden, aber begrenzt auf Userland-Profiling
lttngIdeal, um Informationen zu Kernelprozessen zu sammeln und Multicore-Systeme zu profilierenKann auch zusammen mit Mentors »Sourcery Analyzer« verwendet werden
straceSammeln von Zeiten bei Start/Stopp einer Anwendung/SystemaufrufenKann zu zusätzlicher Systemlast bei der Programmausführung führen, ist aber ein mächtiges Messinstrument
initcall_debug Kernel-Flag, Debug-Information während des Treiberstarts Informationen werden in »dmesg« ausgegeben. Kann eingesetzt werden, um Möglichkeiten für parallele Prozesse zu identifizieren 
Tabelle 2: Linux-Diagnose-Tools zur Optimierung von Bootzeiten

Die meisten können kostenlos heruntergeladen werden und sind einfach anzuwenden. Einige der Tools verlangsamen jedoch das System, sodass sie nach Abschluss der Optimierungsarbeiten wieder deinstalliert werden sollten.

Leider ist es hier nicht möglich, auf jeden der angeführten Befehle einzugehen, ein kurzes Beispiel für die Anwendung von Bootchart beim SoC »i.MX6« demonstriert jedoch, was möglich ist. Bootchart lässt sich ganz einfach einrichten – man lege einfach einen Pfad zum Bootchart-Daemon an und bestimme, was zu messen ist. Die Ausgabe erfolgt in einer Grafikdatei, die dann nach Belieben angezeigt und analysiert werden kann. Bootchart listet alle Initialisierungsereignisse auf einer Zeitachse in chronologischer Reihenfolge auf. Zusätzlich zu den genannten Werkzeugen bietet Mentor Graphics auch ein Entwicklungsanalyse-Tool unter dem Namen »Mentor Embedded Sourcery Analyzer« an, das sich dazu eignet, die Ausgabe von »lttng« und eine Reihe von system- und anwendungsbezogenen Debug-Daten zu laden. Damit lassen sich reale Messdaten wie etwa Bildwiederholraten mit geringer Prozessleistung und der CPU-Auslastung in Verbindung bringen.

Über den Autor:

Andrew Patterson ist Business Development Director bei Mentor Graphics in der Embedded Software Division.