GNU/Linux >> Tutoriels Linux >  >> Linux

Comment gérer les bibliothèques dynamiques et statiques sous Linux

Linux, en quelque sorte, est une série de bibliothèques statiques et dynamiques qui dépendent les unes des autres. Pour les nouveaux utilisateurs de systèmes basés sur Linux, toute la gestion des bibliothèques peut être un mystère. Mais avec l'expérience, la quantité massive de code partagé intégré au système d'exploitation peut être un avantage lors de l'écriture de nouvelles applications.

Pour vous aider à entrer en contact avec ce sujet, j'ai préparé un petit exemple d'application qui montre les méthodes les plus courantes qui fonctionnent sur les distributions Linux courantes (celles-ci n'ont pas été testées sur d'autres systèmes). Pour suivre ce didacticiel pratique à l'aide de l'exemple d'application, ouvrez une invite de commande et tapez :

$ git clone https://github.com/hANSIc99/library_sample
$ cd library_sample/
$ make
cc -c main.c -Wall -Werror
cc -c libmy_static_a.c -o libmy_static_a.o -Wall -Werror
cc -c libmy_static_b.c -o libmy_static_b.o -Wall -Werror
ar -rsv libmy_static.a libmy_static_a.o libmy_static_b.o
ar :création de libmy_static.a
a - libmy_static_a.o
a - libmy_static_b.o
cc -c -fPIC libmy_shared.c -o libmy_shared.o
cc - shared -o libmy_shared.so libmy_shared.o
$ make clean
rm *.o

Après avoir exécuté ces commandes, ces fichiers doivent être ajoutés au répertoire (exécutez ls pour les voir):

mon_application
libmy_static.a
libmy_shared.so

À propos des liens statiques

Lorsque votre application est liée à une bibliothèque statique, le code de la bibliothèque fait partie de l'exécutable résultant. Ceci n'est effectué qu'une seule fois au moment de la liaison, et ces bibliothèques statiques se terminent généralement par un .a extension.

Une bibliothèque statique est une archive (ar) de fichiers objets. Les fichiers objets sont généralement au format ELF. ELF est l'abréviation de Executable and Linkable Format, qui est compatible avec de nombreux systèmes d'exploitation.

La sortie du file La commande vous indique que la bibliothèque statique libmy_static.a est le ar type d'archive :

$ fichier libmy_static.a
libmy_static.a :archive ar actuelle

Avec ar -t , vous pouvez consulter cette archive ; il affiche deux fichiers objets :

$ ar -t libmy_static.a 
libmy_static_a.o
libmy_static_b.o

Vous pouvez extraire les fichiers de l'archive avec ar -x <archive-file> . Les fichiers extraits sont des fichiers objets au format ELF :

$ ar -x libmy_static.a
$ fichier libmy_static_a.o
libmy_static_a.o :ELF 64 bits LSB déplaçable, x86-64, version 1 (SYSV), non supprimé

À propos des liens dynamiques

Plus de ressources Linux

  • Aide-mémoire des commandes Linux
  • Aide-mémoire des commandes Linux avancées
  • Cours en ligne gratuit :Présentation technique de RHEL
  • Aide-mémoire sur le réseau Linux
  • Aide-mémoire SELinux
  • Aide-mémoire sur les commandes courantes de Linux
  • Que sont les conteneurs Linux ?
  • Nos derniers articles Linux

La liaison dynamique signifie l'utilisation de bibliothèques partagées. Les bibliothèques partagées se terminent généralement par .so (abréviation de "objet partagé").

Les bibliothèques partagées sont le moyen le plus courant de gérer les dépendances sur les systèmes Linux. Ces ressources partagées sont chargées en mémoire avant le démarrage de l'application, et lorsque plusieurs processus nécessitent la même bibliothèque, celle-ci ne sera chargée qu'une seule fois sur le système. Cette fonctionnalité permet d'économiser sur l'utilisation de la mémoire par l'application.

Une autre chose à noter est que lorsqu'un bogue est corrigé dans une bibliothèque partagée, chaque application qui référence cette bibliothèque en profitera. Cela signifie également que si le bug n'est pas détecté, chaque application référente en souffrira (si l'application utilise les parties concernées).

Cela peut être très difficile pour les débutants lorsqu'une application nécessite une version spécifique de la bibliothèque, mais l'éditeur de liens ne connaît que l'emplacement d'une version incompatible. Dans ce cas, vous devez aider l'éditeur de liens à trouver le chemin vers la bonne version.

Bien que ce ne soit pas un problème quotidien, comprendre les liens dynamiques vous aidera sûrement à résoudre ces problèmes.

Heureusement, les mécanismes pour cela sont assez simples.

Pour détecter quelles bibliothèques sont nécessaires au démarrage d'une application, vous pouvez utiliser ldd , qui imprimera les bibliothèques partagées utilisées par un fichier donné :

$ ldd my_app 
        linux-vdso.so.1 (0x00007ffd1299c000)
        libmy_shared.so => ​​introuvable
        libc.so.6 => /lib64/libc.so.6 (0x00007f56b869b000)
        /lib64/ld-linux-x86-64.so.2 (0x00007f56b8881000)

Notez que la bibliothèque libmy_shared.so fait partie du référentiel mais n'est pas trouvé. En effet, l'éditeur de liens dynamique, qui est chargé de charger toutes les dépendances en mémoire avant d'exécuter l'application, ne peut pas trouver cette bibliothèque dans les emplacements standard qu'il recherche.

Erreurs associées aux éditeurs de liens trouvant des versions incompatibles de bibliothèques courantes (comme bzip2 , par exemple) peut être assez déroutant pour un nouvel utilisateur. Une solution consiste à ajouter le dossier du référentiel à la variable d'environnement LD_LIBRARY_PATH pour indiquer à l'éditeur de liens où rechercher la version correcte. Dans ce cas, la bonne version se trouve dans ce dossier, vous pouvez donc l'exporter :

$ LD_LIBRARY_PATH=$(mot de passe):$LD_LIBRARY_PATH
$ export LD_LIBRARY_PATH

Maintenant, l'éditeur de liens dynamique sait où trouver la bibliothèque et l'application peut être exécutée. Vous pouvez relancer ldd pour invoquer l'éditeur de liens dynamique, qui inspecte les dépendances de l'application et les charge en mémoire. L'adresse mémoire est indiquée après le chemin de l'objet :

$ ldd my_app 
        linux-vdso.so.1 (0x00007ffd385f7000)
        libmy_shared.so => ​​/home/stephan/library_sample/libmy_shared.so (0x00007f3fad401000)
        libc.so. 6 => /lib64/libc.so.6 (0x00007f3fad21d000)
        /lib64/ld-linux-x86-64.so.2 (0x00007f3fad408000)

Pour savoir quel éditeur de liens est appelé, vous pouvez utiliser file :

$ file my_app 
my_app :exécutable LSB 64 bits ELF, x86-64, version 1 (SYSV), lié dynamiquement, interpréteur /lib64/ld-linux-x86-64.so.2, BuildID[ sha1]=26c677b771122b4c99f0fd9ee001e6c743550fa6, pour GNU/Linux 3.2.0, non supprimé

L'éditeur de liens /lib64/ld-linux-x86–64.so.2 est un lien symbolique vers ld-2.30.so , qui est l'éditeur de liens par défaut pour ma distribution Linux :

fichier $ /lib64/ld-linux-x86-64.so.2 
/lib64/ld-linux-x86-64.so.2 :lien symbolique vers ld-2.31.so

Retour sur la sortie de ldd , vous pouvez également voir (à côté de libmy_shared.so ) que chaque dépendance se termine par un nombre (par exemple, /lib64/libc.so.6 ). Le schéma de nommage habituel des objets partagés est :

**lib** XYZ.so **.<MAJOR>** . **<MINOR>** 

Sur mon système, libc.so.6 est aussi un lien symbolique vers l'objet partagé libc-2.30.so dans le même dossier :

$ fichier /lib64/libc.so.6 
/lib64/libc.so.6 :lien symbolique vers libc-2.31.so

Si vous rencontrez le problème qu'une application ne démarre pas parce que la bibliothèque chargée a la mauvaise version, il est très probable que vous puissiez résoudre ce problème en inspectant et en réorganisant les liens symboliques ou en spécifiant le chemin de recherche correct (voir "Le chargeur dynamique :ld.so" ci-dessous).

Pour plus d'informations, regardez sur le ldd page de manuel.

Chargement dynamique

Le chargement dynamique signifie qu'une bibliothèque (par exemple, un .so file) est chargé pendant l'exécution d'un programme. Cela se fait en utilisant un certain schéma de programmation.

Le chargement dynamique est appliqué lorsqu'une application utilise des plugins qui peuvent être modifiés pendant l'exécution.

Voir le dlopen page de manuel pour plus d'informations.

Le chargeur dynamique :ld.so

Sous Linux, vous avez principalement affaire à des objets partagés, il doit donc y avoir un mécanisme qui détecte les dépendances d'une application et les charge en mémoire.

ld.so recherche les objets partagés à ces emplacements dans l'ordre suivant :

  1. Le chemin relatif ou absolu dans l'application (codé en dur avec le -rpath option compilateur sur GCC)
  2. Dans la variable d'environnement LD_LIBRARY_PATH
  3. Dans le fichier /etc/ld.so.cache

Gardez à l'esprit que l'ajout d'une bibliothèque à l'archive de la bibliothèque système /usr/lib64 nécessite des privilèges d'administrateur. Vous pouvez copier libmy_shared.so manuellement à l'archive de la bibliothèque et faire fonctionner l'application sans définir LD_LIBRARY_PATH :

unset LD_LIBRARY_PATH
sudo cp libmy_shared.so /usr/lib64/

Lorsque vous exécutez ldd , vous pouvez voir que le chemin d'accès à l'archive de la bibliothèque s'affiche :

$ ldd my_app 
        linux-vdso.so.1 (0x00007ffe82fab000)
        libmy_shared.so => ​​/lib64/libmy_shared.so (0x00007f0a963e0000)
        libc.so.6 => / lib64/libc.so.6 (0x00007f0a96216000)
        /lib64/ld-linux-x86-64.so.2 (0x00007f0a96401000)

Personnaliser la bibliothèque partagée au moment de la compilation

Si vous souhaitez que votre application utilise vos bibliothèques partagées, vous pouvez spécifier un chemin absolu ou relatif lors de la compilation.

Modifiez le makefile (ligne 10) et recompilez le programme en appelant make -B . Ensuite, la sortie de ldd affiche libmy_shared.so est listé avec son chemin absolu.

Modifiez ceci :

CFLAGS =-Wall -Werror -Wl,-rpath,$(shell pwd)  

À cela (assurez-vous de modifier le nom d'utilisateur) :

CFLAGS =/home/stephan/library_sample/libmy_shared.so  

Puis recompilez :

$ make 

Confirmez qu'il utilise le chemin absolu que vous avez défini, que vous pouvez voir sur la ligne 2 de la sortie :

$ ldd my_app
    linux-vdso.so.1 (0x00007ffe143ed000)
        libmy_shared.so => ​​/lib64/libmy_shared.so (0x00007fe50926d000)
        /home/stephan/library_sample/libmy_shared .so (0x00007fe509268000)
        libc.so.6 => /lib64/libc.so.6 (0x00007fe50909e000)
        /lib64/ld-linux-x86-64.so.2 (0x00007fe50928e000)

C'est un bon exemple, mais comment cela fonctionnerait-il si vous faisiez une bibliothèque pour que d'autres puissent l'utiliser ? De nouveaux emplacements de bibliothèque peuvent être enregistrés en les écrivant dans /etc/ld.so.conf ou en créant un <library-name>.conf fichier contenant l'emplacement sous /etc/ld.so.conf.d/ . Ensuite, ldconfig doit être exécuté pour réécrire le ld.so.cache dossier. Cette étape est parfois nécessaire après avoir installé un programme qui apporte avec lui des bibliothèques partagées spéciales.

Voir le ld.so page de manuel pour plus d'informations.

Comment gérer plusieurs architectures

Généralement, il existe différentes bibliothèques pour les versions 32 bits et 64 bits des applications. La liste suivante montre leurs emplacements standard pour différentes distributions Linux :

Famille Red Hat

  • 32 bits :/usr/lib
  • 64 bits :/usr/lib64

Famille Debian

  • 32 bits :/usr/lib/i386-linux-gnu
  • 64 bits :/usr/lib/x86_64-linux-gnu

Famille Arch Linux

  • 32 bits :/usr/lib32
  • 64 bits :/usr/lib64

FreeBSD (technique pas une distribution Linux)

  • 32 bits :/usr/lib32
  • 64 bit :/usr/lib

Savoir où chercher ces bibliothèques clés peut faire des liens de bibliothèque rompus un problème du passé.

Bien que cela puisse être déroutant au début, comprendre la gestion des dépendances dans les bibliothèques Linux est un moyen de se sentir en contrôle du système d'exploitation. Parcourez ces étapes avec d'autres applications pour vous familiariser avec les bibliothèques courantes et continuez à apprendre comment résoudre les problèmes de bibliothèque qui pourraient survenir sur votre chemin.


Linux
  1. Comment définir une adresse IP statique et configurer le réseau sous Linux

  2. Comment gérer l'inventaire des hôtes statiques et dynamiques Ansible

  3. Comment définir une adresse IP statique et modifier la table de routage sous Linux

  4. Comment installer et utiliser Flatpak sous Linux

  5. Comment configurer les en-têtes et les bibliothèques pour le développement Linux

Comment renommer des fichiers et des répertoires sous Linux

Comment compresser des fichiers et des répertoires sous Linux

Comment installer et utiliser PuTTY sous Linux

Comment configurer une adresse IP statique sous Linux et Unix

Comment installer et utiliser phpMyAdmin sous Linux

Comment configurer une adresse IP statique sur Alpine Linux