Innenansichten

Android geht in vielerlei Hinsicht ganz andere Wege als andere Linux-Versionen – das beginnt bei Anpassungen am Kernel und hört bei der virtuellen Maschine Dalvik noch lange nicht auf. Die Besonderheiten der Android-Architektur zu kennen hilft dabei, die Eigenarten der populärsten Linux-Variante zu verstehen.

In Pocket speichern vorlesen Druckansicht
Lesezeit: 10 Min.
Von
  • Arno Becker
Inhaltsverzeichnis

Es ist schon erstaunlich, wie viele Funktionen ein modernes Smartphone in sich birgt: telefonieren, Internet-Zugang, Spiele, Videos drehen … Selbstverständlich ist das nicht, eher ein kleines Wunder: Jede Funktion verbraucht Strom und Speicher, und das sind auf mobilen Geräten sehr endliche Ressourcen. Android ist ein Betriebssystem mit Linux-Kernel für Smartphones, aber auch andere Embedded Systems, das den Beschränkungen solcher Geräte Rechnung trägt. Es lohnt sich, einen genaueren Blick auf Android zu werfen: Vieles, was an der Android-Systemarchitektur besonders ist, hat direkte Auswirkungen auf das Verhalten von Android-Geräten und -Anwendungen.

Android ist eine Open-Source-Plattform, die von der Open Handset Alliance entwickelt wird, einem von Google initiierten breiten Zusammenschluss von Netzbetreibern, Smartphone-, Prozessor- und Chip-Herstellern sowie Softwarefirmen. Kern des Betriebssystems ist ein angepasster Linux-Kernel 2.6. Zudem sind zahlreiche Treiber und Bibliotheken verändert oder vollständig ersetzt – ein normales Linux würde die mobile CPU zu stark belasten, wodurch Anwendungen im Multitasking-Betrieb nicht schnell genug laufen würden und der Akku eines mobilen Geräts im Handumdrehen geleert wäre.

Daher erweitert Android das klassische Power Management des Linux-Kernels, um es an die Gegebenheiten mobiler Hardware anzupassen. So muss das System beispielsweise die Hintergrundbeleuchtung von Tastatur und Bildschirm ein- und ausschalten können. Ebenso muss das System den Status des Akkus überwachen und zuverlässig das Gerät herunterfahren, bevor die Stromversorgung zusammenbricht.

Unter Android läuft jede Anwendung als eigener Prozess, jedoch können die Programme Teile anderer Anwendungen nutzen. Folglich kommunizieren Prozesse intensiv miteinander. Diese Interprozesskommunikation (IPC) bringt normalerweise ein aufwendiges Marshalling und Unmarshalling mit sich – die auszutauschenden Daten müssen zwischen ihrer internen Repräsentation und einem zur Übermittlung geeigneten Format hin- und hergewandelt werden. Das verbraucht nicht nur Speicher, da dazu exzessiv Objekte erzeugt werden müssen, sondern belastet auch die CPU.

Um das zu vermeiden, implementiert Android über einen speziellen Treiber namens Binder eine besonders ressourcenschonende Form der Interprozesskommunikation, die den Datenaustausch zwischen Prozessen mittels Shared Memory realisiert: Programme tauschen per IPC lediglich Referenzen auf Objekte aus, die im Shared Memory abgelegt sind.

Auch für dessen Verwaltung unter Berücksichtigung von Zugriffsberechtigungen enthält Android mit Ashmem einen eigenen Treiber, der Schlüssel zum Zugriff auf geteilte Speicherbereiche vergibt. Alle Prozesse, die den Schlüssel kennen, können Daten über diesen Speicherbereich austauschen und den Schlüssel anschließend verwerfen. Gibt es auf einen Speicherbereich keine Referenz mehr, sind also alle Schlüssel verworfen, gibt ihn der Kernel frei. Wird der Gerätespeicher knapp, kann der Low Memory Killer, ein Bestandteil von Ashmem, auch Speicherbereiche freigeben, auf die es noch Referenzen gibt.

Wie bei modernen Betriebssystemen üblich, arbeitet Android mit einer virtuellen Speicherverwaltung: Der physikalische Speicher wird nicht direkt alloziert, sondern über Tabellen auf virtuelle Speicheradressen abgebildet. Allerdings verwendet Android keinen Swap Space, der normalerweise mit in den virtuellen Speicherbereich eingeht und ihn vergrößert – das System muss mit dem zur Verfügung stehenden Gerätespeicher auskommen. Android-Geräte können daher komplett auf externe Speichermedien wie SD-Karte oder Festplatte verzichten.

Zu den Vorteilen eines virtuellen Speichermanagements gehört, dass über die virtuellen Adressen ein zusammenhängender Speicherbereich zur Verfügung steht, der sich physikalisch über viele verstreute Speicherseiten verteilen kann. Ein weiterer Vorteil ist, dass sich virtuelle Speicherbereiche effizient von mehreren Prozessen nutzen lassen, da jeder Prozess nur die Startadresse und die Größe des Speichers kennen muss, nicht jede einzelne Speicherseite.

Zwei weitere Android-spezifische Kernelmodule, der Kernel-Debugger und der Logger, ermöglichen das Debuggen von Android-Anwendungen sowie die Ausgabe von Logging-Information aus Programmen und deren Auslesen mit dem Kommando logcat.

Auch bei den Änderungen an den Bibliotheken steht die Optimierung des Strom- und Speicherverbrauchs im Vordergrund; allerdings gibt es auch rechtliche Probleme. Anstelle der Glibc verwendet Android die C-Bibliothek Bionic. Sie ist (unter Aufgabe vollständiger Glibc-Kompatibilität) mit gut 200 KByte deutlich kleiner als die Standard-C-Bibliothek von Linux, auf Geschwindigkeit optimiert und um einige Android-spezifische Features erweitert.

So enthält Bionic eine spezielle Pthread-Implementierung, die die Besonderheiten mobiler Geräte berücksichtigt: Hier müssen nicht Tausende Threads parallel laufen, sondern jeder Thread muss vor allem wenig Speicher verbrauchen und schnell starten. Zudem steht die Android-C-Bibliothek nicht wie die Glibc unter der GNU General Public License, sondern unter der liberalen BSD-Lizenz – Google will (mit Ausnahme des Linux-Kernels) bewusst keine GPL-Software in Android, um Probleme wegen deren Copyleft-Klausel zu vermeiden.

Unter den weiteren Bibliotheken findet man viele alte Bekannte, die sich in der Embedded-Linux-Welt bewährt haben: WebKit als Rendering-Engine für den Browser, die für Embedded Systems optimierte 3D-Grafikbibliothek OpenGL ES, SQLite für Datenbankfunktionen und so weiter. Ebenfalls nicht untypisch für Embedded Systems ist das das Fehlen eines Fenstersystems wie X11.

Bis hierhin handelt es sich bei Android also um ein „normales“ Embedded Linux, das durchaus in die Liste der in [1] beschriebenen Systeme passen würde. Was Android in den Status einer eigenen Plattform hebt, ist die konsequente Verwendung der Programmiersprache Java. Das gilt sowohl für den Anwendungsrahmen, der die Hardware und die Betriebssystemfunktionen abstrahiert, als auch für die Anwendungen selbst.

Jede Android-Anwendung läuft in einem eigenen Prozess und in einer eigenen virtuellen Maschine. Dies stellt besondere Anforderungen an die VM, die in Bezug auf Speicherverbrauch und CPU-Last hochgradig optimiert sein muss. Durch die Entwicklung einer eigenen VM für Android hat Google zudem ein weiteres Lizenzproblem umgangen: Die Dalvik Virtual Machine (DVM) beruht im Kern auf der quelloffenen Java-VM Apache Harmony. Google-Mitarbeiter Dan Bornstein ist der verantwortliche Entwickler und die DVM nach dem Ort Dalvik in Island benannt, aus dem einige seiner Verwandten kommen.

Der Systemaufbau von Android oberhalb des Kernels unterscheidet sich deutlich von Linux-Versionen für Desktop-Systeme oder Server.

Die Dalvik Virtual Machine arbeitet mit einem eigenen Bytecode. Android-Programme werden zwar in Java geschrieben und mit dem Compiler des Java-SDK zunächst in Java-Bytecode kompiliert, dann aber von einem Tool namens dx in dex-Bytecode (Dalvik Executable Bytecode) für die DVM übersetzt. Dabei landen sämtliche Klassen in einer einzigen dex-Datei. Durch zahlreiche Optimierungen ist diese Datei recht kompakt und kleiner als die gezippten Class-Dateien.

Zum Erzeugen einer Android-Anwendung kommt während des Build-Prozesses ein weiteres Tool zum Einsatz: Das Android Asset Packaging Tool (aapt) fügt alle Programmbestandteile zu einer Datei mit der Endung .apk zusammen. Neben der dex-Datei mit dem Bytecode gehören Ressourcen wie Bilder, Texte und Sound-Dateien sowie das sogenannte „Android Manifest“ zu einer Android-Anwendung. Eine solche apk-Datei kann man mit dem Tool adb (Android Debug Bridge) direkt auf einem Android-Gerät installieren.

Ist eine Anwendung erst einmal installiert und gestartet, läuft sie in einer Sandbox in einem geschützten Speicherbereich. Daten kann sie im Verzeichnis /data/data des internen Gerätespeichers ablegen. Für jede Anwendung existiert hier ein Verzeichnis mit dem Namen des Package, wie es im Android Manifest angegeben wurde. Dateien landen dort im Ordner files, Datenbanken im Ordner databases – eine explizite Pfadangabe ist nicht nötig. Anwendungseinstellungen werden als XML-Datei im Ordner shared_prefs gespeichert.

Außerdem können Anwendungen Daten in einem anwendungseigenen Bereich auf der SD-Karte ablegen, den andere Anwendungen nicht lesen können, oder in öffentlichen Ordnern für andere Anwendungen zugänglich machen. Allerdings sind auch die in einem anwendungseigenen Bereich auf der SD-Karte gespeicherten Daten nicht besonders sicher: Sie lassen sich leicht auslesen, wenn man direkt auf die SD-Karte zugreift. Daher sollten sicherheitsrelevante Daten auf der SD-Karte immer verschlüsselt werden.

Daten, die auf dem Gerät in /data/data gespeichert werden, sind relativ sicher – solange das Gerät nicht gerootet wird. Daher empfiehlt es sich auch hier, sicherheitsrelevante Daten zu verschlüsseln. Das ist jedoch nicht ganz trivial, da Android einen zentralen Schlüsselspeicher (Keystore) für Zertifikate besitzt, den sich alle Anwendungen teilen. Aus Sicherheitsgründen lässt Android keinen Import von Zertifikaten zu, die nicht von einer Certification Authority wie Verisign verifiziert sind. Da verifizierte Zertifikate Geld kosten, müssen Entwickler einen Trick nutzen, der die Verwendung selbst erstellter Zertifikate ermöglicht.

Android verwendet das Dateisystem YAFFS (Yet Another Flash File System); Android 2.3 wechselt auf das Linux-Standard-Dateisystem Ext4, das bei Schreib- und Leseoperationen deutlich schneller sein soll. Leider werden wohl nicht alle Hardwarehersteller beim Update auf Android 2.3 diese Änderung mitmachen und noch das alte YAFFS-Dateisystem ausliefern. Einige Hardwarehersteller verwenden zudem ein eigenes Dateisystem, Samsung beispielsweise seine FAT-Erweiterung Robust Fat Filesystem (RFS).

Als Datenbank verwendet Android SQLite, ein quelloffenes, kompaktes, für den Einsatz auf mobilen Systemen optimiertes relationales Datenbanksystem. SQLite bietet die meisten Funktionen, die man von größeren Datenbanksystemen gewohnt ist: SQL-Syntax, Transaktionen, Prepared Statements und so weiter. Die Datenbank verbraucht dabei jedoch zur Laufzeit nur sehr wenig Speicher in der Größenordnung 175 bis 250 KByte

SQLite wird als Bibliothek direkt zu den Anwendungen hinzugelinkt und benötigt daher keinen Datenbankserver: Anwendungen definieren eine Datenbank und können sie sofort verwenden, ohne dass zuvor ein Datenbankserver starten muss. Genau wie bei Dateien können sich mehrere Anwendungen eine Datenbank teilen. Die Datenbank selbst wird in Form einer einzelnen Datei mit der Endung .db im Ordner databases des Anwendungsverzeichnisses abgelegt.

Den vollständigen Artikel finden Sie in c't 4/2011.

Mehr Infos

Inside Android

Artikel zum Thema "Inside Android" finden Sie in c't 4/2011:

(odi)