Aus Linux-Magazin 04/2009

Linux portieren

© sxc.hu

Computer, Handys, Mediaplayer und Supermarktkassen – Linux ist auf unterschiedlichster Hardware anzutreffen. Ein Schlüssel für diese Anpassungsfähigkeit des freien Betriebssystems ist unter anderem die GNU Compiler Collection.

Es gibt kaum eine Rechnerarchitektur, auf der der Linux-Kernel nicht läuft. Wenn es eine gibt, finden sich meist sehr schnell ein paar Programmierer, die für Abhilfe sorgen. Die Geschichte der Linux-Portierung ist fast so alt wie der Kernel selbst: Kernel-Vater Linus Torvalds selbst übertrug seinen für x86 geschriebenen Systemkern auf die Alpha-Architektur. Nur wenig später fand Linux seinen Weg auf Sparc-Rechner. Die jüngsten Ports übertragen Linux auf die Embedded-Architekturen AVR32 und Blackfin.

Weltenbummler

Dass Linux jemals so viele fremde Welten erobern würde, war zumindest 1991 noch nicht absehbar. Linus Torvalds selbst hat angenommen, sein “Terminal-Emulator” sei nicht portabel, da er das Task-Switching der x86-Architektur verwendete [1]. Dank der frei verfügbaren GNU Compiler Collection (GCC) entwickelte sich Linux aber schnell zu einem der am besten portierbaren Systeme. Die Hersteller von Embedded-Systemen suchten einen hoch anpassbaren Systemkern und fanden ihn in Linux. Weitere Portierungen kamen schlicht deshalb zustande, weil einige Kernelentwickler Linux auch auf ihrer Lieblings-Architektur nutzen wollten.

Erster Brückenschlag

Grundlagen jeder Linux-Portierung sind die Binutils, eine Sammlung von Programmierwerkzeugen für Assembler- und Binärcode, sowie die GCC. Beide müssen zunächst auf dem vom Entwickler genutzten Rechner, dem Host, vorliegen. Der Entwickler richtet auf diesem Rechner – beispielsweise einem gewöhnlichen x86-Computer – eine Umgebung für die Cross-Kompilierung ein. Dazu erstellt er eine Maschinenbeschreibung der Zielmaschine, dem Target.

Die notwendigen Informationen liegen üblicherweise in Form von Hersteller-Spezifikationen vor. Diese Beschreibung und maschinenspezifische Einstellungen nutzen der GNU-Assembler (Gas) und die BFD-Bibliothek aus den Binutils. Sie erzeugen und formatieren damit aus Assembler-Befehlen gültigen Binärcode. Danach nimmt der Entwickler sich die GNU Compiler Collection vor. Sie benötigt ebenfalls ein Beschreibung des Target. Diesmal enthalten die Beschreibungen detaillierte Informationen über die Zielarchitektur, nämlich wie ihre Komponenten sich ansprechen lassen und wie sie miteinander kommunizieren.

Kern-Komponente

Erst dann, wenn die Binutils und die GCC für eine Architektur eingerichtet sind, ist der Kernel selbst an der Reihe. Dazu übersetzt der Entwickler auf einer von Linux bereits unterstützten Maschine den Kernelcode für das Zielsystem. Aber mit dem Übersetzen allein ist es natürlich nicht getan, ein Kernelport setzt zusätzlichen Programmcode voraus. Der Entwickler legt dazu im Verzeichnis »arch« des Kernelcode-Baums ein neues Verzeichnis an.

Meist ist der Bootcode der erste Schritt. Er versetzt das System in einen für Linux geeigneten Betriebsmodus, in dem der Kernel Speicher anfordern kann. Architekturspezifisch ist auch der Code, der Hardwaregeräte erkennt und anspricht. Dabei kann der Entwickler allerdings oft auf generische Bibliotheken für Standardkomponenten wie USB, PCI, SPI und viele weitere Chipsätze zurückgreifen.

Tabellen für Interrupts, Traps, Exceptions und ähnliche maschinenspezifische Einsprungspunkte sind ebenfalls an die neue Architektur anzupassen. Oft übernimmt Linux auch vom Bios bereits initialisierte Hardware und ihre vom Board-Designer festgelegte Konfiguration. Immerhin laufen Zeitgeber und andere Komponenten längst, wenn der Kernel startet.

Ist der Systemkern so weit vorbereitet, steht ein erster Test in einer entsprechend vorbereiteten virtuellen Maschine an. Geht alles glatt, kann der Linux-Kernel das erste Mal auf der Zielhardware laufen – zunächst ohne vollständige Linux-Systemumgebung. Am Ende des Bootprozesses startet der Kernel erst einmal eine minimale Shell. Die eigentliche Kernel-Portierung ist damit geschafft. Zeit, sich um Userspace-Programme zu kümmern.

Vervollständigt

Zu den ersten Schritten für die Portierung der Komponenten im Userspace gehört eine funktionsfähige C-Bibliothek, idealerweise die GNU-Libc oder Glibc. Diese entsteht wieder in der Cross-Compiler-Umgebung. Die Autotools sind Voraussetzung für das Übersetzen weiterer Software. Parallel kann sich der Entwickler aber schon der im Embedded-Bereich verbreiteten Shell und Toolsammlung Busybox [2] widmen, die ohne Autotools übersetzbar ist. Sind beide fertiggestellt, lassen sich bereits viele weitere Programme kompilieren.

Software, die direkt auf vom Kernel bereitgestellte Schnittstellen zugreift, funktioniert jedoch erst nach einer Anpassung. Ein Beispiel dafür ist das X-Window-Systen. Viele andere Anwendungen und Programme sollten sich aber – wenn ihre Entwickler auf Portabilität geachtet haben – ohne große Anpassungen kompilieren lassen. Ist das Zielsystem ein ziemlich leistungsschwacher Embedded-Rechner, bietet die Cross-Kompilierung auf einer x86-Maschine einen Geschwindigkeitsvorteil.

Manchmal gibt sich auch weniger systemnahe Software beim Cross-Kompilieren überraschend sperrig. Berüchtigt ist in Entwicklerkreisen beispielsweise der Perl-Interpreter – er leistet sich etliche Allüren, die auf der neuen Architektur neu zu implementieren sind, was viel Zeit kostet. Die häufigste Fehlerquelle ist aber eine falsche oder unvollständige Beschreibung der Zielmaschine in der Cross-Kompilier-Umgebung.

Manche Architekturen bieten kaum die Mindestvoraussetzungen für eine Portierung. Doch nur in seltenen Fällen ist sie unmöglich. Beispiele sind 8-Bit-Architekturen und Mikrocontroller mit nur wenigen KByte adressierbarem RAM. Nach Aussage von Entwicklern treten Überraschungen bei Linux dennoch vergleichsweise selten auf.

Abbildung 1: Beim Portieren entstehen in einer Cross-Kompilier-Umgebung zuerst die Binaries für GCC und Binutils. Die Libc bildet zusammen mit den Autotools und einer Shell die Grundlage für Userspace-Systemkomponenten.

Abbildung 1: Beim Portieren entstehen in einer Cross-Kompilier-Umgebung zuerst die Binaries für GCC und Binutils. Die Libc bildet zusammen mit den Autotools und einer Shell die Grundlage für Userspace-Systemkomponenten.

Allgegenwärtig

Heute befeuert der flexible Linux-Systemkern gut zwei Dutzend verschiedene Computerarchitekturen – von kleinsten Embedded-System im Sicherungskasten bis hin zu den leistungsfähigsten Großrechnern der Welt. Nur Net BSD kann mit ähnlich vielen unterstützte Systemarchitekturen aufwarten. Wer selbst portieren möchte, findet unter »Documentation/arm/Porting« im Source-Tarball des Kernels ein anschauliches Beispiel. (pkr)

Infos

[1] Linus\’ Ankündigung von Linux: [http://groups.google.de/group/comp.os.minix/msg/b813d52cbc5a044b]

[2] Busybox: [http://www.busybox.net]

Die Autoren

Jan Rähm ist Wissenschaftsjournalist. Er schreibt, funkt und bloggt Geschichten aus und über Linux, IT und Technik. Außer für das Linux-Magazin arbeitet er für den Deutschlandfunk, das Deutschlandradio Kultur und für andere Medien.

Ingo Oeser arbeitet als Kernelentwickler und Linux-Systemadministrator. Er hat Linux mit der Muttermilch aufgesogen und kann heute davon nicht mehr lassen.

LINUX-MAGAZIN KAUFEN
EINZELNE AUSGABE Print-Ausgaben Digitale Ausgaben
ABONNEMENTS Print-Abos Digitales Abo
TABLET & SMARTPHONE APPS Readly Logo
E-Mail Benachrichtigung
Benachrichtige mich zu:
0 Kommentare
Älteste
Neuste Beste Bewertung
Inline Feedbacks
Alle Kommentare anzeigen
Nach oben