Kapitel 10. Linux®-Binärkompatibilität

10.1. Übersicht

FreeBSD bietet Binärkompatibilität zu Linux®, so dass Benutzer Linux® Anwendungen auf einem FreeBSD-System installieren und ausführen können, ohne die Binärdatei ändern zu müssen. Es wurde sogar berichtet, dass in einigen Situationen Linux® Anwendungen auf FreeBSD besser laufen als unter Linux®.

Allerdings werden einige Linux®-spezifischen Merkmale nicht von FreeBSD unterstützt. Linux®-Anwendungen, die i386™-spezifische Aufrufe, wie bspw. die Aktivierung des virtuellen 8086-Modus verwenden, werden derzeit nicht unterstützt.

Die Unterstützung für 64-Bit-Binärkompatibilität für Linux® wurde in FreeBSD 10.3 hinzugefügt.

Nach dem Lesen dieses Kapitels werden Sie wissen:

  • Wie Sie die Linux®-Binärkompatibilität aktivieren.

  • Wie zusätzliche Linux®-Systembibliotheken installiert werden.

  • Wie Sie Linux®-Anwendungen unter FreeBSD installieren.

  • Wie die Linux®-Binärkompatibilität unter FreeBSD implementiert ist.

Bevor Sie dieses Kapitel lesen, sollten Sie wissen:

10.2. Konfiguration der Linux®-Binärkompatibilität

Die Linux®-Binärkompatibilität ist per Voreinstellung nicht aktiviert und auch Linux®-Bibliotheken werden nicht installiert. Linux®-Bibliotheken können entweder manuell, oder aus der FreeBSD Ports-Sammlung installiert werden.

Bevor Sie versuchen den Port zu bauen, laden Sie das Linux®-Kernelmodul, da ansonsten der Bau fehlschlägt:

# kldload linux

Für 64-Bit Kompatibilität:

# kldload linux64

Prüfen Sie, ob das Modul geladen wurde:

% kldstat
Id Refs Address    Size     Name
 1    2 0xc0100000 16bdb8   kernel
 7    1 0xc24db000 d000     linux.ko

Der einfachste Weg um einen Basissatz von Linux®-Bibliotheken und Binärdateien auf einem FreeBSD-System zu installieren, ist über den Port oder das Paket emulators/linux_base-c7. So installieren Sie das Paket:

# pkg install emulators/linux_base-c7

Wollen Sie die Linux®-Binärkompatibilität beim Systemstart aktivieren, fügen Sie folgende Zeile in /etc/rc.conf hinzu:

linux_enable="YES"

Auf 64-Bit Maschinen wird das Modul für die 64-Bit Emulation automatisch von /etc/rc.d/abi geladen.

Seitdem die Linux®-Binärkompatibilität Unterstützung für die Ausführung von 32- und 64-Bit-Linux®-Binärdateien erhalten hat, ist es nicht mehr möglich, die Emulationsfähigkeit in einen angepassten Kernel zu integrieren.

10.2.1. Manuelle Installation zusätzlicher Bibliotheken

Wenn sich eine Linux®-Anwendung über fehlende Bibliotheken beschwert nachdem die Linux®-Binärkompatibilität installiert wurde, finden Sie heraus welche Bibliothken die Anwendung benötigt und installieren Sie diese manuell.

Mit ldd können Sie unter Linux® bestimmen, welche gemeinsam benutzten Bibliotheken eine Anwendung benötigt. Wenn Sie herausfinden wollen, welche Bibliotheken linuxdoom benötigt, können Sie folgenden Befehl auf einem Linux®-System ausführen, welches Doom installiert hat:

% ldd linuxdoom
libXt.so.3 (DLL Jump 3.1) => /usr/X11/lib/libXt.so.3.1.0
libX11.so.3 (DLL Jump 3.1) => /usr/X11/lib/libX11.so.3.1.0
libc.so.4 (DLL Jump 4.5pl26) => /lib/libc.so.4.6.29

Kopieren Sie alle Dateien aus der letzten Spalte der Ausgabe von einem Linux®-System auf das FreeBSD-System in das Verzeichnis /compat/linux. Nach dem Kopieren erstellen Sie symbolische Links auf die Namen in der ersten Spalte. In diesem Beispiel werden folgende Dateien auf dem FreeBSD-System installiert:

/compat/linux/usr/X11/lib/libXt.so.3.1.0
/compat/linux/usr/X11/lib/libXt.so.3 -> libXt.so.3.1.0
/compat/linux/usr/X11/lib/libX11.so.3.1.0
/compat/linux/usr/X11/lib/libX11.so.3 -> libX11.so.3.1.0
/compat/linux/lib/libc.so.4.6.29
/compat/linux/lib/libc.so.4 -> libc.so.4.6.29

Wenn Sie bereits eine Linux®-Bibliothek einer zur ersten Spalte passenden Hauptversionsnummer besitzen, muss sie nicht mehr kopiert werden, da die bereits vorhandene Version funktionieren sollte. Hat die Bibliothek jedoch eine neuere Versionsnummer, sollten Sie sie dennoch kopieren. Sie können die alte Version löschen, solange Sie einen symbolischen Link auf die neue Version anlegen.

Folgende Bibliotheken existieren bereits auf dem FreeBSD-System:

/compat/linux/lib/libc.so.4.6.27$
/compat/linux/lib/libc.so.4 -> libc.so.4.6.27

ldd zeigt an, dass eine Anwendung eine neuere Version benötigt:

libc.so.4 (DLL Jump 4.5pl26) -> libc.so.4.6.29

Wenn diese Bibliotheken sich nur um ein oder zwei Stellen in der Unterversionsnummer unterscheiden, sollte das Programm dennoch mit der älteren Version funktionieren. Wenn Sie wollen, können Sie die bestehende libc.so durch die neuere Version ersetzen:

/compat/linux/lib/libc.so.4.6.29
/compat/linux/lib/libc.so.4 -> libc.so.4.6.29

Der Mechanismus der symbolischen Links wird nur für Linux®-Binärdateien benötigt. Nach einer Weile wird es eine ausreichende Menge an Linux®-Bibliotheken auf dem System geben, sodass Sie neu installierte Linux®-Anwendungen ohne zusätzlichen Aufwand auf dem System laufen lassen können.

10.2.2. Linux® ELF-Binärdateien installieren

ELF-Binärdateien benötigen manchmal eine zusätzliche "Kennzeichnung". Wenn Sie versuchen, eine nicht gekennzeichnete ELF-Binärdatei auszuführen, werden Sie eine Fehlermeldung ähnlich der folgenden erhalten:

% ./my-linux-elf-binary
ELF binary type not known
Abort

Damit der FreeBSD-Kernel eine Linux®-ELF-Datei von einer FreeBSD-ELF-Datei unterscheiden kann, gibt es das Werkzeug brandelf(1).

% brandelf -t Linux my-linux-elf-binary

Die GNU Werkzeuge schreiben nun automatisch die passende Kennzeichnungsinformation in die ELF-Binärdateien, so dass Sie diesen Schritt in Zukunft nur noch selten benötigen.

10.2.3. Installieren einer RPM-basierten Linux®-Anwendung

Wenn Sie eine Linux® RPM-basierte Anwendung installieren möchten, installieren Sie zunächst den Port oder das Paket archivers/rpm4. Anschließend kann der Superuser das folgende Kommando benutzen, um ein .rpm zu installieren:

# cd /compat/linux
# rpm2cpio < /pfad/zum/linux.archiv.rpm | cpio -id

Fall notwendig, benutzen Sie brandelf auf den installierten ELF-Binärdateien. Beachten Sie, dass dies eine saubere Deinstallation verhindert.

10.2.4. Namensauflösung konfigurieren

Wenn DNS nicht funktioniert, oder die folgende Fehlermeldung erscheint:

resolv+: "bind" is an invalid keyword resolv+:
"hosts" is an invalid keyword

müssen Sie /compat/linux/etc/host.conf wie folgt bearbeiten:

order hosts, bind
multi on

Diese Reihenfolge legt fest, dass zuerst /etc/hosts und anschließend DNS durchsucht werden. Wenn /compat/linux/etc/host.conf nicht vorhanden ist, nutzen Linux®-Anwendungen /etc/host.conf und beschweren sich über die inkompatible FreeBSD-Syntax. Wenn Sie in /etc/resolv.conf keinen Nameserver konfiguriert haben, sollten Sie den Eintrag bind entfernen.

10.3. Weiterführende Themen

Dieser Abschnitt beschreibt wie die Linux®-Binärkompatibilität funktioniert. Die folgenden Informationen stammen aus einer E-Mail, die von Terry Lambert (tlambert@primenet.com) an FreeBSD chat 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.

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.

FreeBSD verfügt über eine Liste von Ladern, anstelle eines einzigen, auf #! zurückgreifenden Laders, um Shell-Interpreter oder Shell-Skripte auszuführen.

Für die Linux® ABI-Unterstützung erkennt FreeBSD die magische Zahl als ELF-Binärdatei. 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 mit brandelf(1) als Linux gekennzeichnet werden:

# brandelf -t Linux file

Wenn der ELF-Lader die Linux-Kennzeichnung sieht, wird ein Zeiger in der proc-Struktur ersetzt. Alle Systemaufrufe werden durch diesen Zeiger indiziert. 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 für den Systemaufruf aus der proc-Struktur und erhält damit die Linux®-Eintrittspunkte für den Systemaufruf.

Zusätzlich verändert der Linux®-Modus die Systempfade dynamisch; genauso, wie dies die Option union beim Einbinden von Dateisystemen macht. Zuerst wird die Datei im Verzeichnis /compat/linux/Originalpfad gesucht, wenn sie dort nicht gefunden wurde, wird sie im 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 /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 verwendet werden. Linux®-Binärdateien hingegen verwenden die Linux®-glue-Funktionen. FreeBSD-glue-Funktionen sind statisch in den Kernel gelinkt, Linux®-glue-Funktionen sind statisch gelinkt oder können über ein ladbares Kernelmodul eingebunden werden.

Technisch gesehen ist dies nicht wirklich eine Emulation, sondern eine ABI-Implementation. Es wird manchmal "Linux® Emulation" genannt, da es zu einer Zeit implementiert wurde, in der es kein anderes Wort gab, das beschrieb, was vor sich ging. Es war falsch zu behaupten, FreeBSD würde Linux®-Binärprogramme ausführen, da der Code nicht unter FreeBSD übersetzt wurde.


All FreeBSD documents are available for download at https://download.freebsd.org/ftp/doc/

Questions that are not answered by the documentation may be sent to <freebsd-questions@FreeBSD.org>.
Send questions about this document to <freebsd-doc@FreeBSD.org>.