Raspbian bootet auf den RasPis zwar schnell, aber für manche Anwendungsfälle nicht schnell genug. Ein paar Kniffe reduzieren die Boot-Zeit spürbar.
In verschiedenen Foren findet sich auf Nachfragen zu Optimierungen der Boot-Zeit oft die Empfehlung, den RasPi einfach durchlaufen zu lassen. Allerdings ist das nicht immer eine Option – sei es, weil eine dauerhaft freie Steckdose fehlt, sei es, weil der Mini-Rechner an einer Batterie hängt. Ausgangspunkt für diesen Artikel war der Bau eines Küchenweckers: Der soll nach dem Einstecken so schnell wie möglich starten, denn in der Küche will man nur auf das Essen warten.
Ein anderes Anwendungsszenario beschreibt ein Blog-Eintrag, in dem es um eine batteriebetriebene Wildkamera geht [1]. Per Bewegungssensor gestartet, soll sie möglichst schnell ein Bild aufnehmen. Von dort stammen auch viele der weiter unten aufgeführten Anpassungen.
Mess-Pi
Am Anfang der Untersuchungen stand die Frage, wie sich die Boot-Zeit eines RasPi möglichst einfach messen lässt. Erste manuelle Tests mit der Stoppuhr in der Hand waren nicht sehr ermutigend. Ein weiterer Mini-Rechner, der “Mess-Pi”, übernimmt daher diese Aufgabe (Abbildung 1). Er besitzt ein kleinen Display für die Anzeige der Sekunden sowie einen Summer für akustische Rückmeldungen. Details zum Aufbau sowie das Python-Skript dahinter finden Sie im Github-Repository des Autors [2].

Abbildung 1: Die Schaltung des Mess-Pi: Er misst die Boot-Geschwindigkeit des zweiten RasPi.
Das zu messende System hängt an einem Wide-Input-Shim von Pimoroni. Dabei handelt es sich um einen kleinen Stromversorgungsbaustein für den RasPi, der Eingangsspannungen von 5 bis 16 Volt unterstützt (Abbildung 2). Für den Test spielt es zwar keine Rolle, aber der Baustein bringt vorne rechts auch einen Enable-Pin mit. Darüber schaltet der Mess-Pi den Strom ein und startet gleichzeitig die Stoppuhr. Als Alternative zum Wide-Input-Shim eignet sich auch ein USB-Powerswitch [3].

Abbildung 2: Ein Wide-Input-Shim mit Enable-Pin. Er startet die Stromzufuhr zum zweiten RasPi und gleichzeitig die Stoppuhr.
Unser Anwendungsprogramm auf dem Test-RasPi besteht dann aus nur wenigen Zeilen des Shell-Skripts bootende.sh (Listing 1), das GPIO6 auf Low setzt. Per Jumper mit dem Mess-Pi verbunden, erhält der Mess-Pi so das Ende-Signal und hält die Stoppuhr an.
Listing 1
#!/bin/bash gpio -g 6 mode out gpio -g 6 write 0
Nachdem der Messaufbau steht, geht es jetzt an eine lange Abfolge von Tests in verschiedenen Konstellationen, um die Zeitfresser beim Systemstart zu identifizieren und zu beseitigen.
Ausgangslage
Die Basismessung erfolgt mit Debian “Buster” Lite vom 26.09.19, das nach dem Booten wie üblich eine Grundkonfiguration erhielt. Das einzige zusätzlich installierte Paket ist wiringpi. Es stellt das Kommando gpio bereit, das wir wie oben beschrieben für unser Anwendungsprogramm benötigen. Masse und GPIO6 verbindet ein Jumperkabel mit dem Mess-Pi (Abbildung 3).

Abbildung 3: Zum präzisen Messen der tatsächlichen Boot-Zeit kommt ein weiterer RasPi zum Einsatz, im Bild der hinten mit dem Display.
Für den ersten Test schreiben Sie den Aufruf /usr/local/bin/bootende.sh in die Datei /etc/rc.local vor dem exit in der letzten Zeile. Das System führt dieses Skript am Ende des Boot-Vorgangs aus. Auch wenn viele Tutorials und Anleitungen rund um den RasPi dieses Vorgehen empfehlen, erwies es sich im Test als nicht besonders sinnvoll – eine Schraube lässt sich ja durchaus auch mit einem Hammer erfolgreich ins Holz treiben. Nach diesen Vorbereitungen fahren wir das System herunter, setzen den Mess-Pi zurück und starten den Messvorgang.
Das Booten unterteilt sich in drei Phasen: Zuerst erfolgt die Initialisierung der Hardware durch die Platine. Nach dem Initialisieren der GPU und CPU lädt die Firmware den Kernel, der wiederum auf Kernel-Ebene die Hardware initialisiert. An dieser Stelle kommt die /boot/config.txt ins Spiel: Sie bestimmt die Art und Weise, wie der Kernel diverse Hardware-Komponenten verwendet. Nach dem Hochfahren des Kernels übergibt dieser die Steuerung an den Init-Prozess, der wiederum mit dem Dienst Systemd alle notwendigen Anwendungsprozesse startet.
Die erste Phase lässt sich nicht direkt messen, sondern nur als Differenz aus der Gesamtzeit des Boot-Vorgangs minus der Zeit für die Kernel-Initialisierung und die Zeit für den Systemstart ausrechnen. Letzteres ist aber ein schwammiger Begriff, denn Linux sieht den Systemstart ab dem Moment als beendet an, an dem alle zum Booten definierten Programme laufen. Bei einem Datenbank-Server bedeutet der Programmstart aber noch lange nicht, dass die Datenbank tatsächlich bereitsteht.
Für die Boot-Analyse stellt Systemd das Tool Systemd-analyze bereit. Der einfachste Aufruf mit dem Argument time gibt eine Zusammenfassung nach Boot-Phasen aus (Abbildung 4). Die Zeiten zeigen, dass die Distribution die überwiegende Zeit nach der Kernel-Initialisierung beim Hochfahren des Systems vertrödelt.

Abbildung 4: Ausgabe der Boot-Zeit mit dem Befehl systemd-analyze time.
Interessanter als die Gesamtzeit ist die Zeit bis zum Start eines speziellen Diensts. Dazu verwenden Sie statt des Arguments time den Parameter critical-chain (Abbildung 5). Als Argument dient ein Systemd-Target oder ein Service. Wir verwenden hier den vom System automatisch generierten Dienst rc-local.service, da wir ja das Anwendungsprogramm aus der /etc/rc.local heraus starten.

Abbildung 5: Die Ausgabe des Befehls systemd-analyze critical-chain rc-local.service.
An dieser Stelle zeigt sich, dass das nur bedingt eine gute Wahl ist. Zum einen lässt sich die Abarbeitung der rc.local nicht beeinflussen – Abbildung 5 zeigt, dass das erst nach der vollständigen Netzwerkkonfiguration geschieht. Zum anderen bezieht man so nur Informationen über den Start der rc.local, nicht aber über den Start des eigenen Anwendungsprogramms. In unserem Fall ist das zwar quasi identisch, aber das ist nicht generell so.
Eigenen Service etablieren
Der erste Schritt zum Optimieren der Boot-Zeiten führt also über die Definition eines eigenen Services. Das gelingt mit wenigen Zeilen in einer Textdatei, die Sie in /etc/systemd/system/bootende.service anlegen (Listing 2). Den Service aktivieren Sie mit folgendem Kommando:






