Wenn Sie sich fragen, wie die Linux-Binärkompatibilität
unter FreeBSD realisiert wurde, sollten Sie diesen Abschnitt lesen.
Der Großteil der folgenden Informationen stammt aus einer
E-Mail, die von Terry Lambert (<tlambert@primenet.com>
)
an die FreeBSD-Chat-Mailingliste
(<freebsd-chat@FreeBSD.org>
) geschrieben wurde
(Message ID: <199906020108.SAA07001@usr09.primenet.com>
).
FreeBSD verfügt über eine „execution class loader“ genannte Abstraktion. Dabei handelt es sich um einen Eingriff in den execve(2) Systemaufruf.
FreeBSD verfügt über eine Liste von Ladern, anstelle
eines einzigen, auf #!
zurückgreifenden Laders, um Shell-Interpreter oder Shell-Skripte
auszuführen.
Historisch gesehen untersuchte der einzige, auf UNIX-Plattformen vorhandene Lader die "magische Zahl" (in der Regel die ersten 4 oder 8 Bytes der Datei), um festzustellen, ob der Binärtyp dem System bekannt war. War dies der Fall, wurde der Binärlader aufgerufen.
Wenn es sich nicht um den zum System gehörigen Binärtyp handelte, gab execve(2) einen Fehler zurück, und die Shell versuchte stattdessen, die Datei als Shell-Befehl auszuführen.
Dabei wurde als Standardeinstellung „was auch immer die aktuelle Shell ist“ festgelegt.
Später wurde ein Hack in sh(1) eingefügt,
der die zwei ersten Zeichen untersuchte. Wenn diese
:\n
entsprachen,
wurde stattdessen die csh(1)-Shell aufgerufen
(wir glauben, dass dies zuerst von SCO umgesetzt wurde).
FreeBSD versucht heute eine Liste von Ladern, unter denen
sich ein allgemeiner Lader für Interpreter befindet. Der
auszuführende Interpreter wird im ersten, durch
Leerzeichen getrennten Feld, der #!
-Zeile
angegeben. Lässt sich der Interpreter nicht ermitteln,
wird auf /bin/sh
zurückgegriffen.
Für die Linux ABI-Unterstützung erkennt FreeBSD die magische Zahl als ELF-Binärdatei (Zu diesem Zeitpunkt wird nicht zwischen FreeBSD, Solaris™, Linux oder anderen Systemen unterschieden, die über ELF-Binärdateien verfügen.).
Der ELF-Lader sucht nach einer speziellen Kennzeichnung, die aus einem Kommentarabschnitt in der ELF-Datei besteht, und die in SVR4/Solaris™ ELF Binärdateien nicht vorhanden ist.
Damit Linux-Binärdateien (unter FreeBSD) funktionieren,
müssen sie als Linux
gekennzeichnet werden, und zwar durch
brandelf(1):
#
brandelf -t Linux file
Nachdem dies geschehen ist, erkennt der ELF-Lader die
Linux
-Kennzeichnung der Datei.
Wenn der ELF-Lader die Linux
-Kennzeichnung
sieht, wird ein Zeiger in der proc
-Struktur
ersetzt. Alle Systemaufrufe werden durch diesen Zeiger indiziert
(in einem traditionellen UNIX® System wäre das ein
sysent[]
-Strukturfeld, das die Systemaufrufe
enthält). Der Prozess wird weiterhin speziell gekennzeichnet,
so dass der Trap-vector im Signal-trampoline-code eine spezielle
Behandlung erfährt und das Linux-Kernelmodul verschiedene
kleinere Korrekturen vornehmen kann.
Der Linux-Systemaufrufvektor enthält neben anderen
Dingen eine Liste der sysent[]
-Einträge,
deren Adressen sich im Kernelmodul befinden.
Wenn ein Linux-Programm einen Systemaufruf ausführt, dereferenziert die Trap-Behandlungsroutine den Zeiger auf die Eintrittspunkte für die Systemaufrufe und erhält damit die Linux-Eintrittspunkte und nicht die FreeBSD-Eintrittspunkte.
Zusätzlich verändert der
Linuxmodus die Systempfade dynamisch; genauso, wie dies die
Option union
beim Einbinden von Dateisystemen
macht (Achtung: nicht das Dateisystem unionfs!).
Zuerst wird die Datei im Verzeichnis /compat/linux/
gesucht, danach, wenn sie dort nicht gefunden
wurde, wird sie im FreeBSD-Verzeichnis
Originalpfad
/
gesucht. Dadurch wird sichergestellt, dass
Binärdateien, die zur Ausführung andere
Binärdateien benötigen, ausgeführt
werden können (so dass alle Linux-Werkzeuge unter der
ABI laufen). Dies bedeutet auch,
dass Linux-Binärdateien FreeBSD-Binärdateien
laden und ausführen können, wenn keine passenden
Linux-Binärdateien vorhanden sind. Ein in
Originalpfad
/compat/linux
plaziertes uname(1) kann
damit Linux-Programmen vorgaukeln, dass sie auf einem Linux-System
laufen.
Im Endeffekt gibt es einen Linux-Kernel innerhalb des
FreeBSD-Kernels. Die Sprungtabellen für Linux-
beziehungsweise FreeBSD-Systemaufrufe verweisen allerdings auf
dieselben Funktionen, die Kerneldienste wie Dateisystemoperationen,
Operationen für den virtuellen Speicher,
Signalübermittlung und System V IPC bereitstellen,
Der einzige Unterschied ist, dass Binärdateien unter FreeBSD
FreeBSD-glue-Funktionen verwenden.
Linux-Binärdateien hingegen verwenden die
Linux-glue-Funktionen. Die meisten
älteren Betriebssysteme hatten ihre eigenen
glue-Funktionen: Funktionsadressen
in einem globalen, statischen sysent[]
Strukturfeld an Stelle von Funktionsadressen, die durch
einen dynamisch initialisierten Zeiger aus der
proc
Struktur, die den Aufruf gemacht hatte,
dereferenziert wurden.
Welche ist die echte FreeBSD-ABI? Das spielt keine Rolle. Grundsätzlich ist der einzige Unterschied (zurzeit ist das so; dies könnte sich in zukünftigen Versionen leicht ändern und wird sich wahrscheinlich auch ändern), dass die FreeBSD-glue-Funktionen statisch in den Kernel gelinkt sind, und dass die Linux-glue-Funktionen statisch gelinkt oder über ein Modul eingebunden werden können.
Ja, aber ist das wirkliche eine Emulation? Nein. Es ist eine Implementierung eines ABIs, keine Emulation. Es ist kein Emulator (oder Simulator, um der nächsten Frage zuvorzukommen) beteiligt.
Warum wird es manchmal „Linux-Emulation“ genannt? Um es schwerer zu machen, FreeBSD zu verkaufen. Wirklich, das kommt daher, weil dies zu einer Zeit implemtiert wurde, in der es kein anderes Wort (als Emulation) gab, das beschrieb, was vor sich ging. Wenn der Kernel nicht entsprechend konfiguriert wurde oder das Modul geladen wurde, war es falsch zu behaupten, FreeBSD würde Linux-Binärprogramme ausführen. Man benötigte ein Wort, das beschrieb, was da geladen wurde – daher „Der Linux-Emulator“.
Wenn Sie Fragen zu FreeBSD haben, schicken Sie eine E-Mail an
<de-bsd-questions@de.FreeBSD.org>.
Wenn Sie Fragen zu dieser Dokumentation haben, schicken Sie eine E-Mail an
<de-bsd-translators@de.FreeBSD.org>.