---
title: Kapitel 10. Linux®-Binärkompatibilität
part: Teil II. Oft benutzte Funktionen
prev: books/handbook/printing
next: books/handbook/partiii
showBookMenu: true
weight: 13
params:
  path: "/books/handbook/linuxemu/"
---

[[linuxemu]]
= Linux(R)-Binärkompatibilität
:doctype: book
:toc: macro
:toclevels: 1
:icons: font
:sectnums:
:sectnumlevels: 6
:sectnumoffset: 10
:partnums:
:source-highlighter: rouge
:experimental:
:images-path: books/handbook/linuxemu/

ifdef::env-beastie[]
ifdef::backend-html5[]
:imagesdir: ../../../../images/{images-path}
endif::[]
ifndef::book[]
include::shared/authors.adoc[]
include::shared/mirrors.adoc[]
include::shared/releases.adoc[]
include::shared/attributes/attributes-{{% lang %}}.adoc[]
include::shared/{{% lang %}}/teams.adoc[]
include::shared/{{% lang %}}/mailing-lists.adoc[]
include::shared/{{% lang %}}/urls.adoc[]
toc::[]
endif::[]
ifdef::backend-pdf,backend-epub3[]
include::../../../../../shared/asciidoctor.adoc[]
endif::[]
endif::[]

ifndef::env-beastie[]
toc::[]
include::../../../../../shared/asciidoctor.adoc[]
endif::[]

[[linuxemu-synopsis]]
== Übersicht

FreeBSD bietet Binärkompatibilität zu Linux(R), so dass Benutzer Linux(R) 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(R) Anwendungen auf FreeBSD besser laufen als unter Linux(R).

Allerdings werden einige Linux(R)-spezifischen Merkmale nicht von FreeBSD unterstützt. Linux(R)-Anwendungen, die i386(TM)-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(R) wurde in FreeBSD 10.3 hinzugefügt.

Nach dem Lesen dieses Kapitels werden Sie wissen:

* Wie Sie die Linux(R)-Binärkompatibilität aktivieren.
* Wie zusätzliche Linux(R)-Systembibliotheken installiert werden.
* Wie Sie Linux(R)-Anwendungen unter FreeBSD installieren.
* Wie die Linux(R)-Binärkompatibilität unter FreeBSD implementiert ist.

Bevor Sie dieses Kapitel lesen, sollten Sie wissen:

* Wie Sie crossref:ports[ports,Software von Drittanbietern installieren].

[[linuxemu-lbc-install]]
== Konfiguration der Linux(R)-Binärkompatibilität

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

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

[source,shell]
....
# kldload linux
....

Für 64-Bit Kompatibilität:

[source,shell]
....
# kldload linux64
....

Prüfen Sie, ob das Modul geladen wurde:

[source,shell]
....
% 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(R)-Bibliotheken und Binärdateien auf einem FreeBSD-System zu installieren, ist über den Port oder das Paket package:emulators/linux_base-c7[]. So installieren Sie das Paket:

[source,shell]
....
# pkg install emulators/linux_base-c7
....

Wollen Sie die Linux(R)-Binärkompatibilität beim Systemstart aktivieren, fügen Sie folgende Zeile in [.filename]#/etc/rc.conf# hinzu:

[.programlisting]
....
linux_enable="YES"
....

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

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

[[linuxemu-libs-manually]]
=== Manuelle Installation zusätzlicher Bibliotheken

Wenn sich eine Linux(R)-Anwendung über fehlende Bibliotheken beschwert nachdem die Linux(R)-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(R) 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(R)-System ausführen, welches Doom installiert hat:

[source,shell]
....
% 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(R)-System auf das FreeBSD-System in das Verzeichnis [.filename]#/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:

[source,shell]
....
/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(R)-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:

[source,shell]
....
/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:

[source,shell]
....
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 [.filename]#libc.so# durch die neuere Version ersetzen:

[source,shell]
....
/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(R)-Binärdateien benötigt. Nach einer Weile wird es eine ausreichende Menge an Linux(R)-Bibliotheken auf dem System geben, sodass Sie neu installierte Linux(R)-Anwendungen ohne zusätzlichen Aufwand auf dem System laufen lassen können.

=== Linux(R) 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:

[source,shell]
....
% ./my-linux-elf-binary
ELF binary type not known
Abort
....

Damit der FreeBSD-Kernel eine Linux(R)-ELF-Datei von einer FreeBSD-ELF-Datei unterscheiden kann, gibt es das Werkzeug man:brandelf[1].

[source,shell]
....
% 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.

=== Installieren einer RPM-basierten Linux(R)-Anwendung

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

[source,shell]
....
# 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.

=== Namensauflösung konfigurieren

Wenn DNS nicht funktioniert, oder die folgende Fehlermeldung erscheint:

[source,shell]
....
resolv+: "bind" is an invalid keyword resolv+:
"hosts" is an invalid keyword
....

müssen Sie [.filename]#/compat/linux/etc/host.conf# wie folgt bearbeiten:

[.programlisting]
....
order hosts, bind
multi on
....

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

[[linuxemu-advanced]]
== Weiterführende Themen

Dieser Abschnitt beschreibt wie die Linux(R)-Binärkompatibilität funktioniert. Die folgenden Informationen stammen aus einer E-Mail, die von Terry Lambert (mailto:tlambert@primenet.com[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 man:execve[2] Systemaufruf.

Historisch gesehen untersuchte der einzige, auf UNIX(R)-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 man: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 man:sh[1] eingefügt, der die zwei ersten Zeichen untersuchte. Wenn diese `:\n` entsprachen, wurde stattdessen die man: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(R) 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(TM) ELF Binärdateien nicht vorhanden ist.

Damit Linux(R)-Binärdateien unter FreeBSD funktionieren, müssen sie mit man:brandelf[1] als `Linux` _gekennzeichnet_ werden:

[source,shell]
....
# 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(R)-Kernelmodul verschiedene kleinere Korrekturen vornehmen kann.

Der Linux(R)-Systemaufrufvektor enthält neben anderen Dingen eine Liste der `sysent[]`-Einträge, deren Adressen sich im Kernelmodul befinden.

Wenn ein Linux(R)-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(R)-Eintrittspunkte für den Systemaufruf.

Zusätzlich _verändert_ der Linux(R)-Modus die Systempfade dynamisch; genauso, wie dies die Option `union` beim Einbinden von Dateisystemen macht. Zuerst wird die Datei im Verzeichnis [.filename]#/compat/linux/Originalpfad# gesucht, wenn sie dort nicht gefunden wurde, wird sie im Verzeichnis [.filename]#/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(R)-Werkzeuge unter der ABI laufen). Dies bedeutet auch, dass Linux(R)-Binärdateien FreeBSD-Binärdateien laden und ausführen können, wenn keine passenden Linux(R)-Binärdateien vorhanden sind. Ein in [.filename]#/compat/linux# plaziertes man:uname[1] kann damit Linux(R)-Programmen vorgaukeln, dass sie auf einem Linux(R)-System laufen.

Im Endeffekt gibt es einen Linux(R)-Kernel innerhalb des FreeBSD-Kernels. Die Sprungtabellen für Linux(R)- 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(R)-Binärdateien hingegen verwenden die Linux(R)-_glue_-Funktionen. FreeBSD-_glue_-Funktionen sind statisch in den Kernel gelinkt, Linux(R)-_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(R) 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(R)-Binärprogramme ausführen, da der Code nicht unter FreeBSD übersetzt wurde.
