Chapitre 10. Compatibilité binaire avec Linux®

10.1. Synopsis

FreeBSD fournit une compatibilité binaire avec Linux®, permettant aux utilisateurs d’installer et d’exécuter la plupart des applications Linux® sur un système FreeBSD sans avoir à modifier ces applications. On rapporte également que dans certaines situations, les binaires Linux sont plus performants sous FreeBSD que sous Linux®,.

Il existe cependant certaines caractéristiques spécifiques à Linux®, qui ne sont pas supportées sous FreeBSD. Par exemple, des binaires Linux® ne fonctionneront pas sous FreeBSD s’ils utilisent massivement des appels i386™ spécifiques, comme activation du mode virtuel 8086.

Le support de la compatibilité Linux® pour les binaires 64bits a été ajouté avec FreeBSD 10.3.

Après la lecture de ce chapitre, vous connaîtrez:

  • Comment activer la compatibilité binaire avec Linux® sur un système FreeBSD.

  • Comment installer des bibliothèques partagées Linux® supplémentaires.

  • Comment installer des application Linux® sur un système FreeBSD.

  • Les détails de l’implémentation de la compatibilité Linux® sous FreeBSD.

Avant de lire ce chapitre, vous devrez:

10.2. Configurer la compatibilité binaire avec Linux®

Par défaut, les bibliothèques Linux® ne sont pas installées et la compatibilité binaire avec Linux n’est pas activée. Les bibliothèques Linux® peuvent être installées soit manuellement soit à partir du catalogue des logiciels portés.

Avant de tenter de compiler un logiciel, charger le module du noyau Linux®, sinon la compilation risque d’échouer:

# kldload linux

Pour une compatibilité en 64bits:

# kldload linux64

Pour vérifier que le module est bien chargé:

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

Le logiciel précompilé emulators/linux_base-c7 ou la version compilée à partir du catalogue des logiciels portés est la méthode la plus simple pour installer l’ensemble des bibliothèques et binaires de base Linux® sur un système FreeBSD. Pour installer le logiciel porté:

# pkg install emulators/linux_base-c7

Pour activer au démarrage la compatibilité Linux®, ajouter ligne suivante au fichier /etc/rc.conf:

linux_enable="YES"

Sur les machines 64bits, /etc/rc.d/abi chargera automatiquement le module pour l’émulation 64bits.

Depuis qu’à été ajouté le support pour l’exécution des binaires Linux® 32 et 64 bits à la couche de compatibilité Linux® (sur les hôtes 64 bits de type x86), il n’est plus possible d’ajouter l’émulation en statique dans un noyau personnalisé.

Pour certaines applications, /compat/linux/proc, /compat/linux/sys, et /compat/linux/dev/shm pourront nécessiter d’être montés. Ajoutez la ligne suivante au fichier /etc/fstab:

linprocfs  /compat/linux/proc     linprocfs   rw            0   0
linsysfs   /compat/linux/sys      linsysfs    rw            0   0
tmpfs      /compat/linux/dev/shm  tmpfs       rw,mode=1777  0   0

Puis montez les systèmes de fichiers en conséquence:

# mount /compat/linux/sys
# mount /compat/linux/proc
# mount /compat/linux/dev/shm

10.2.1. Installer des bibliothèques supplémentaires à la main

Si une application Linux® se plaint de l’absence d’une bibliothèque partagée après avoir configuré la compatibilité binaire Linux®, déterminez quelle est la bibliothèque partagée nécessaire au binaire Linux® et installez-la à la main.

A partir d’un système Linux®, la commande ldd peut être utilisée pour déterminer quelles sont les bibliothèques partagées dont l’application a besoin. Par exemple, pour contrôler quelles bibliothèques partagées sont nécessaires à linuxdoom, exécuter cette commande à partir d’un système Linux® où est installé Doom:

% 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

Ensuite, copier tous les fichiers mentionnés dans la dernière colonne, du système sous Linux® vers /compat/linux sur le système FreeBSD. Une fois copiés, créer les liens symboliques vers les noms de fichiers donnés dans la première colonne. Cet exemple donnera lieu aux fichiers suivants sur le système FreeBSD:

/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

Si une bibliothèque Linux® partagée existe avec le même numéro de version majeure que celle indiquée par la première colonne du résultat de la commande ldd, il est inutile de la copier vers le nom de fichier donné par la dernière colonne, la bibliothèque déjà existante devrait fonctionner. Il est cependant recommandé de copier malgré tout la bibliothèque partagée si c’est une version récente. L’ancienne version peut être supprimée, du moment que le lien symbolique pointe sur la nouvelle.

Par exemple, les bibliothèques suivantes existent déjà sur le système FreeBSD:

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

et ldd indique qu’un binaire a besoin d’une version plus récente:

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

Etant donné que la bibliothèque existante n’a qu’une ou deux versions de retard sur le dernier digit, le programme devrait fonctionner avec la version légèrement plus ancienne. Il est, néanmoins, plus sûr de remplacer la libc.so existante avec la version plus récente:

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

Généralement, vous ne devrez cherchez à savoir de quelles bibliothèques partagées dépendent les binaires Linux® que les premières fois que vous installerez des programmes Linux® sur le système FreeBSD. Au bout d’un moment, il y aura un ensemble suffisant de bibliothèques partagées Linux® sur le système pour être en mesure d’exécuter les binaires Linux® nouvellement importés sans effort supplémentaire.

10.2.2. Installer des binaires Linux® ELF

Une étape supplémentaire est parfois nécessaire pour les binaires ELF. Quand un binaire ELF non marqué est exécuté, une erreur sera générée:

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

Pour que le noyau FreeBSD puisse distinguer un binaire ELF FreeBSD d’un binaire Linux®, vous devez employer l’utilitaire brandelf(1):

% brandelf -t Linux mon-binaire-elf-linux

Les outils GNU incorporent désormais automatiquement les marques nécessaires dans les binaires ELF, cette étape n’est généralement pas nécessaire.

10.2.3. Installer une application Linux® basée sur RPM

Pour installer une application Linux® basée sur RPM, installer en premier le logiciel précompilé ou porté archivers/rpm4. Une fois installé, root peut utiliser la commande suivante pour installer un .rpm:

# cd /compat/linux
# rpm2cpio  /path/to/linux.archive.rpm | cpio -id

Si nécessaire, utiliser brandelf sur les binaires ELF installés. Il faut noter que cela empêchera une desinstallation propre.

10.2.4. Configurer le résolveur de noms de domaines

Si le DNS ne fonctionne pas, ou si cette erreur apparaît
resolv+: "bind" is an invalid keyword resolv+:
"hosts" is an invalid keyword

Vous devrez configurer un fichier /compat/linux/etc/host.conf contenant:

order hosts, bind
multi on

Cela indique qu’il faut tout d’abord regarder dans le fichier /etc/hosts puis interroger le DNS. Quand le fichier /compat/linux/etc/host.conf n’existe pas, les applications Linux® trouvent le fichier /etc/host.conf et se plaignent de sa syntaxe FreeBSD incompatible. Supprimez bind si un serveur de noms n’est pas configuré avec le fichier /etc/resolv.conf.

10.3. Sujets avancés

Cette section décrit comment la compatibilité binaire avec Linux® fonctionne, et est basée sur un courrier électronique de Terry Lambert tlambert@primenet.com envoyé à la liste de diffusion pour la discussion de sujets non-techniques en rapport avec FreeBSD (Message ID: 199906020108.SAA07001@usr09.primenet.com).

FreeBSD possède une abstraction appelée "chargeur de classe d’exécution". C’est une portion de l’appel système execve(2).

Historiquement, le chargeur UNIX® examinait le nombre magique (généralement les 4 ou 8 premiers octets du fichier) pour voir si c’était un binaire connu par le système, et si c’était le cas, invoquait le chargeur binaire.

Si ce n’était pas le type de binaire du système, l’appel execve(2) retournait un échec, et l’interpréteur de commandes tentait de l’exécuter comme une commande d’interpréteur. Cette hypothèse était celle par défaut "quelque soit l’interpréteur de commandes actuel".

Plus tard, une modification a été faite sur sh(1) pour examiner les deux premiers caractères, et s’ils étaient :\n, alors elle invoquait l’interpréteur de commandes csh(1) à la place.

FreeBSD possède désormais une liste de chargeurs, avec un chargeur par défaut, #!, pour exécuter les interpréteurs ou les procédures de commandes.

Pour le support de l’ABI Linux®, FreeBSD voit le nombre magique comme un binaire ELF. Le chargeur ELF recherche une marque spécifique, qui se trouve dans une section de commentaires dans l’image ELF, et qui n’est pas présente dans les binaires SVR4/Solaris™ ELF.

Pour que les binaires Linux® puissent fonctionner, ils doivent être marqués sous le type Linux avec brandelf(1):

# brandelf -t Linux file

Lorsque le chargeur ELF voit le marquage Linux, le chargeur remplace un pointeur dans la structure proc. Tous les appels système sont indexés par l’intermédiaire de ce pointeur (dans un système UNIX® traditionnel, cela serait la structure sysent[], contenant les appels système). De plus, le processus est marqué pour une gestion spéciale du vecteur d’interruption ("trap") pour le signal de code "trampoline", et plusieurs autres corrections (mineures) qui sont gérées par le noyau Linux®.

Le vecteur d’appel système Linux® contient, entre autres, une liste des entrées sysent[] dont les adresses résident dans le noyau.

Quand un appel système est effectué par le binaire Linux, le code "trap" déréférence de la structure proc le pointeur de la fonction de l’appel système, et utilise les points d’entrée Linux®, et non pas FreeBSD, de d’appel système.

Le mode Linux® redéfinit dynamiquement l’origine des requêtes. C’est, en effet, équivalent à l’option union de montage des systèmes de fichiers. Tout d’abord, une tentative est faite pour rechercher le fichier dans le répertoire /compat/linux/chemin-origine. Si cela échoue, la recherche est effectuée dans le répertoire /chemin-origine. Cela permet de s’assurer que les binaires nécessitant d’autres binaires puissent s’exécuter. Par exemple, l’ensemble des outils Linux® peuvent tourner sous l’ABI Linux®. Cela signifie également que les binaires Linux® peuvent charger et exécuter les binaires FreeBSD, s’il n’y a pas de binaires Linux® correspondant présents, et vous pourriez placer une commande uname(1) dans l’arborescence /compat/linux pour vous assurer que les binaires Linux® ne puissent pas dire qu’ils ne tournent pas sous Linux®.

En effet, il y a un noyau Linux® dans le noyau FreeBSD. Les diverses fonctions sous-jacentes qui implémentent tous les services fournis par le noyau sont identiques entre les deux tables d’entrées des appels systèmes FreeBSD et Linux®: les opérations sur les systèmes de fichiers, les opérations sur la mémoire virtuelle, la gestion des signaux, iet l’IPC System V. La seule différence est que les binaires FreeBSD utilisent les fonctions glue de FreeBSD, et les binaires Linux® celles de Linux®. Les fonctions glue de FreeBSD sont liées en statique dans le noyau, les fonctions glue Linux® peuvent être liées statiquement, ou l’on peut y accéder via un module du noyau.

Techniquement, ce n’est pas vraiment de l’émulation, c’est l’implémentation d’une interface binaire pour les applications (ABI). Cela est parfois appelé "émulation Linux®" parce que l’implémentation a été faite à une époque où il n’y avait pas vraiment d’autres mots pour décrire ce qui était en développement. Dire que FreeBSD exécutait les binaires Linux® n’était pas vrai, jusqu’à ce le code de support Linux® soit compilé ou le module soit chargé.


Ce document, ainsi que d'autres peut être téléchargé sur https://download.freebsd.org/ftp/doc/

Pour toutes questions à propos de FreeBSD, lisez la documentation avant de contacter <freebsd-questions@FreeBSD.org>.
Pour les questions sur cette documentation, contactez <freebsd-doc@FreeBSD.org>.