Ein Angebot von

Embedded Linux – Kernel, Aufbau, Toolchain

| Autor / Redakteur: Andreas Klinger / Sebastian Gerstl

Beim Einsatz des Open Source Betriebssystems Linux in Embedded Systemen kommt es auf deutlich mehr an, als "nur" den richtigen Kernel zu wählen. Die folgenden Grundlagen sind im Embedded Linux System essentiell.
Beim Einsatz des Open Source Betriebssystems Linux in Embedded Systemen kommt es auf deutlich mehr an, als "nur" den richtigen Kernel zu wählen. Die folgenden Grundlagen sind im Embedded Linux System essentiell. (Bild: Clipdealer)

Wenn Linux in einem Embedded System eingesetzt werden muss, sind die Ressourcen deutlich beschränkter als in einem Desktop- oder Server-System. Worauf kommt es im Embedded Linux hinsichtlich Kernel, Bootloader oder Root-Filesystem genau an?

Woraus besteht ein Linux-System?

Linux-Systeme bestehen aus drei Komponenten: Bootloader, Linux-Kernel und Root-Filesystem.

Der Bootloader hat die Aufgabe beim Booten die Hardware zu initialisieren, den Kernel ins RAM zu kopieren, ihn mit erforderlichen Informationen zu versorgen und zum Starten zu bringen. Ist dies erfolgt, geht sein Ausführungspfad in den Kernel-Bootvorgang über.

Der Linux-Kernel beinhaltet die Speicherverwaltung, Scheduling, Interprozess-Kommunikation sowie eine riesige Auswahl an Treibern. Jeglicher Zugriff auf Hardware erfolgt mithilfe von Kerneltreibern, zumindest um ihn einzurichten.

Am Ende des Bootvorganges hängt der Kernel das Root-Filesystem ein. Dies wird als "Mounten" bezeichnet. Dieses ist ab dem Root-Verzeichnis / sichtbar. In ihm befindet sich der Init-Dämon. Dieser setzt den Bootvorgang im Userspace fort. Dazu werden weitere Dateisysteme gemountet, Systemeinstellungen vorgenommen und Dämonen (Hintergrundprozesse) gestartet. Ausserdem startet er Login-Programme, welche nach Authentifizierung eines Benutzers jeweils eine Shell starten.

Worin unterscheiden sich nun Embedded-Linux-Systeme von Desktop- und Server-Linux-Systemen? Um diese Frage zu klären werden nachfolgend die erforderlichen Komponenten beschrieben und ein Vergleich von Standard- und Embedded-Linux hergestellt.

Bootloader in Embedded Linux

Welcher Bootloader eingesetzt wird hängt von der Architektur ab. Auf Intel-Systemen kommt meist der Bootloader grub zum Einsatz, während bei Nicht-Intel-Systemen meist u-boot oder barebox eingesetzt werden. Diese Unterteilung ist zwar nicht fix vorgegeben und die Bootloader können theoretisch auch auf anderen Architekturen laufen. Praktisch hat dies jedoch nur wenig Relevanz.

Grund dafür dürfte vor allem sein, dass sich Intel-Architekturen in der Art und Weise, wie Hardwareinformationen an den Bootloader und den Linux-Kernel geliefert werden, auszeichnen. Bei Intel gibt es dazu das BIOS, welches mittels ACPI diese Informationen an die Software liefert. Darauf aufbauend kann diese dann die entsprechenden Treiber laden und verwenden. Dadurch ist es möglich, dass ein und dasselbe Bootloader-Executable auf unterschiedlichen Boards der Architektur Intel eingesetzt wird, wie dies bei grub der Fall ist.

Ist keine generische Informationsquelle vorhanden, aus welcher die Hardwarekonfiguration ausgelesen werden kann, muss der Bootloader diese Informationen zumindest teilweise fix einkompilliert haben. Das ist bei den aus dem Mikrocontrollerbereich stammenden Bootloadern u-boot und barebox der Fall. Diese werden immer für eine bestimmte (Unter-)Architektur erstellt, häufig sogar für ein spezielles Board mit einer spezifischen Hardware-Konfiguration.

Ob es sich also nun um ein Embedded-, Desktop- oder Server-System handelt, spielt bei der Auswahl des Bootloaders also eine untergeordnete Rolle.

Aufbau eines Embedded-Linux-Systems.
Aufbau eines Embedded-Linux-Systems. (Bild: Andreas Klinger)

Zusammenstellung von Kernel und Rootfilesystem

Für die Zusammenstellung eines Embedded-Linux-Systems gibt es zwei konträre Vorgehensweisen. Beim Top-Down-Ansatz wird eine Distribution, welche bereits eine große Anzahl an Softwarepaketen enthält auf die Notwendigkeiten des Zielsystems reduziert.

Dies funktioniert natürlich nur, wenn eine Distribution für die entsprechende Architektur verfügbar ist. Für Embedded-Systeme existiert zum Beispiel das System elbe, welches nach diesem Prinzip funktioniert.

Beim Bottom-Up-Ansatz wird dagegen das komplette System aus den Sourcen heraus erstellt. Dies wird jedoch meist nicht komplett "From-The-Scratch" durchgeführt. Meist lässt sich der Entwickler von einem Buildsystem unterstützen. Dieses hat die Aufgabe, den Erstellvorgang angefangen von der Cross-Development-Toolchain über Bootloader, Kernel und Root-Filesystem zu automatisieren. Der Entwickler wählt die Architektur, Softwarepakete, Versionen und so weiter aus und überlässt den Erstellvorgang dem Buildsystem. Beispiele dafür sind buildroot und yocto.

Toolchain für Embedded Linux

Beim Bottom-Up-Ansatz benötigt man eine Development-Toolchain, mit welcher es möglich ist, die Komponenten zu erstellen. Sehr häufig wird auf einem Entwicklungssystem mit anderer Architektur als dem Zielsystem erstellt. In diesem Fall wird eine Cross-Development-Toolchain benötigt. Bei den Buildsystemen sind diese Toolchains mit enthalten.

Bestandteil der Toolchain ist neben dem Compiler und den Binutils (Assembler, Linker, Objdump, ...) auch die Libraries des Zielsystems, gegen welche die Programme des Root-Filesystems gelinkt werden. Vor allem die sogenannte C-Library ist hier von zentraler Bedeutung.

Für Desktop- und Server-Systeme wird als C-Library fast ausschließlich die GNU-C-Library, kurz glibc, verwendet. Diese enthält immer die aktuellsten Features, welche vom Kernel angeboten werden.

Bei Embedded-Linux kann ebenso die glibc verwendet werden. In Fällen jedoch, in denen die Größe dieser Library störend ist, weil ein kleines System benötigt wird, ist sie oftmals zu groß. Dafür existieren schlankere Re-Implementierungen. Diese sind viel kleiner durch das Weglassen von Debugging-, Tracing- und Profiling-Funktonalitäten. Auch sind sie konfigurierbar in ihrem Funktionsumfang.

Die Konsequenz ist jedoch, dass Programme des Root-Filesystems immer gegen genau die korrekte C-Library gelinkt werden müssen. Ansonsten kann es passieren, dass sie nicht funktionieren. Die glibc dagegen wird binarkompatibel gehalten, so dass Binärprogramme ausgetauscht werden können. Dies funktioniert bei den abgespeckten Libraries nur sehr bedingt. Beispiele für kleine C-Libraries sind uClibc und musl.

Mainline-Kernel, zubehöriger Patch, oder doch ein Manufacturer-Kernel? Welcher Kernel für ein Embedded-System eingesetzt werden kann hängt massgeblich davon ab, wie gut es Hersteller oder Community gelungen ist, Architekturanpassungen und Treiber vorzunehmen und zu veröffentlichen.
Mainline-Kernel, zubehöriger Patch, oder doch ein Manufacturer-Kernel? Welcher Kernel für ein Embedded-System eingesetzt werden kann hängt massgeblich davon ab, wie gut es Hersteller oder Community gelungen ist, Architekturanpassungen und Treiber vorzunehmen und zu veröffentlichen. (Bild: Andreas Klinger)

Embedded Linux Kernel

Distributionen, wie sie vor allem für Desktop- und Server-Systeme eingesetzt werden liefern sowohl einen Linux-Kernel als auch ein Root-Filesystem mit. Die darin enthaltenen Kernel sind zunächst Mainline-Kernel plus einer häufig sehr grossen Anzahl an Patches. Diese Patches werden zur Behebung von Bugs oder zur Schliessung von Sicherheitslücken eingebracht und mit der Distribution verteilt. Die Zusammenstellung und Erstellung dieser Patches ist eine wichtige Aufgabe der Distributionshersteller.

Für Embedded-Systeme kommen Distributions-Kernel meistens nicht in Betracht. Dies liegt zum einen an der eingesetzten Architektur. Zum anderen sind Embedded Boards selbst bei gleicher Architektur meist spezifischer, ihre Hardwarebestückung entsprechend oft nicht von verfügbaren Distributionen abgedeckt.

Welcher Kernel nun für ein Embedded-System eingesetzt werden kann hängt maßgeblich davon ab, wie gut es dem Hersteller bzw. der Community es bisher gelungen ist, Architekturanpassungen und Treiber upstream zu übermitteln. Sprich, ob Kernelanpassungen überhaupt erstellt und wenn ja, diese dann in den Mainline-Kernel aufgenommen wurden. An diesem Punkt gibt es große Unterschiede zwischen den SOC- und Board-Herstellern.

Im Idealfall kann man einen Mainline-Kernel nehmen und hat dann die freie Auswahl, welche Version man verwenden möchte, ob ggf. noch ein Echtzeit-Patch eingesetzt werden soll, oder ob man in der Zukunft einfach auf eine neuere Version wechseln kann.

Existiert diese Möglichkeit nicht, ist man häufig auf einen sogenannten Manufacturer-Kernel angewiesen. Dies ist ein Mainline-Kernel, welcher durch Patches des Chipherstellers und weiter durch den Boardhersteller angepasst wurde, so dass der Kernel auf dem entsprechenden Board läuft. In diesem Fall ist man auf die verfügbaren Versionen angewiesen und hat es sehr schwer auf eine andere (aktuellere) Kernel-Version zu wechseln, wenn diese nicht gleichzeitig vom Hersteller bereitgestellt wird. Erfahrungsgemäß werden in solch einem Fall nur einige wenige Kernelversionen bereitgestellt und irgendwann in der Zukunft gar keine neuen Versionen mehr.

Dann sitzt man als Entwickler auf diesem Kernel und hat kaum Freiheitsgrade. So kann es passieren, dass man einen Treiber benötigt, ein neues Kernel-Feature einsetzen oder eine Sicherheitslücke schließen möchte. In all diesen Fällen ist es schwierig vorhandene Lösungen in das eigene System zu integrieren und meist mit erheblichem Entwicklungsaufwand verbunden.

Man kann bereits vor Auswahl eines Boards anhand des Umfanges der notwendigen Patches und daran wie tiefschürfend die Änderungen sind, erkennen, wie weit man sich durch dessen Einsatz von der Mainline entfernt und damit Freiheitsgrade aufgibt.

Root-Filesystem

Das Root-Filesystem besteht aus einem Verzeichnissystem mit den wichtigsten Programmen sowie Device-Nodes und Libraries. Die benötigten Programme können entweder die Originalprogramme oder reduzierte Varianten sein. In Embedded-Linux-Systemen werden aus Platzgründen sehr häufig reduzierte Varianten eingesetzt. Diese werden dann oftmals mithilfe der Busybox erstellt. Dies ist eine Re-Implementierung der wichtigsten Programme mit dem Ziel möglichst kleiner Footprint. Dies wird durch Weglassen von Funktionalität erreicht. Zudem ist der Umfang an Programmen sowie deren Features konfigurierbar.

Eine weitere Auswahl betrifft den Init-Dämon. Bei Desktop-Systemen hat sich inzwischen der systemd durchgesetzt. Bei Embedded-Systemen kommen alternativ das klassische System-V-Init und das daran angelehnte aber reduzierte Busybox-Init in Frage.

Häufig erstellt man vom Embedded-Linux zwei unterschiedliche Systeme für die gleiche Hardware. Eine Variante, welche das eigentliche Produkt werden soll sowie eine zweite Variante für Entwicklungszwecke. Bei der Entwicklungsvariante findet man einen angepassten Kernel sowie Programme für das Debuggen und Tracen. Dies kommt daher, dass die Auswahl an Programmen, die für das fertige System benötigt werden, meist sehr überschaubar ist.

Embedded-Linux-Distributionen

Bei Standard-Linux werden in den meisten Fällen Distributionen eingesetzt. Diese beinhalten neben der Zusammenstellung der Software-Pakete, eine ihnen eigene Paketverwaltung, Verzeichnisaufbau und so weiter.

Das Pendant für Embedded-Linux sind sogenannte Buildsysteme. Mit ihnen können ganze Embedded-Linux-Systeme gebaut werden, das heißt sie bilden den gesamten Erstellvorgang von der Cross-Development-Toolchain über den Bootloader, den Linux-Kernel bis hin zum Root-Filesystem ab. Der komplette Erstellvorgang kann mit ihnen abgebildet werden.

Dabei ist es möglich, im Buildsystem alle notwendigen Vorgaben zu machen, wie die Architektur, welche Compiler-Version, welche Libraries, welche Programme ins Root-Filesystem sollen und so weiter. Beispiele dafür sind crosstool-ng, buildroot, yocto und elbe.

Mit crosstool-ng kann eine Cross-Toolchain für ein Target-System erstellt werden. Die anderen Komponenten (Bootloader, Kernel, Root-Filesystem) können damit nicht erstellt werden.

Bei buildroot ist der komplette Erstellvorgang mit allen Komponenten abgebildet. Dieser wird mittels einer semigraphischen Oberfläche eingestellt und mit Makefiles durchgeführt.

yocto hingegen arbeitet mit sogenannten Rezepten. Diese beinhalten die Erstellvorschriften für die einzelnen Komponenten. Beim Erstellen werden dann diese Rezepte mit dem Tool bitbake abgearbeitet.

Mit elbe wird das Embedded-System nicht "from-the-scratch" erstellt, sondern mithilfe von debootstrap in einer virtualisieren Umgebung das Zielsystem aus Debian-Paketen heraus erstellt.

Zusammenfassung

Desktop- bzw. Server-Linux-Systemene sind mit einer Reihe an Distributionen abgedeckt und in Ihrem Aufbau vergleichsweise homogen. Embedded-Linux-Systeme dagegen sind sehr viel heterogener. Gründe dafür sind in der verfügbaren Hardware und den Anforderungen an das fertige Embedded-System zu suchen und können zu ganz unterschiedlichen Systemen führen.

Ein Embedded-Echtzeit-Linux-System aufsetzen (Teil 1)

Ein Embedded-Echtzeit-Linux-System aufsetzen (Teil 1)

23.02.12 - Ein Embedded-Board, eine JTAG-Schnittstelle und freie Software – mehr braucht man nicht für ein fertiges Entwicklungssystem für Embedded-Echtzeit-Linux. Dieses Tutorial zeigt Ihnen, wie das geht. lesen

Ein Embedded- Echtzeit-Linux-System aufsetzen, (Teil 2)

Ein Embedded- Echtzeit-Linux-System aufsetzen, (Teil 2)

01.05.12 - In diesem Embedded-Linux-Tutorial erfahrt Ihr, wie ihr einen Bootloader erstellt und modifiziert. Außerdem kümmern wir uns um den Linux-Kernel und das Root-Filesystem. lesen

Linux Secure Boot in der Praxis

Linux Secure Boot in der Praxis

27.02.18 - Embedded Systeme sind zunehmenden Angriffen aus unterschiedlichen Quellen ausgesetzt.. Der auf diesen Systemen ausgeführte Code muss daher aus vertrauenswürdigen Quellen kommen. Zentrales Element ist hier die Code-Integritätsprüfung während des Boot-Vorgangs. lesen

Kommentar zu diesem Artikel abgeben
Grüß Gott Herr Weigelt, dieser Artikel dient nicht dazu die vielen Buildsysteme zu bewerten. Es...  lesen
posted am 08.07.2018 um 12:40 von Unregistriert

Ich muß ich doch sehr wundern, daß hier PTXDist als Buildsystem nicht genannt wird. Schließlich...  lesen
posted am 07.07.2018 um 11:17 von Unregistriert


Mitdiskutieren
copyright

Dieser Beitrag ist urheberrechtlich geschützt. Sie wollen ihn für Ihre Zwecke verwenden? Infos finden Sie unter www.mycontentfactory.de (ID: 45326335 / Open Source)