Je suis conscient que les objets partagés sous Linux utilisent "so nombres", à savoir que différentes versions d'un objet partagé reçoivent des extensions différentes, par exemple:
example.so.1
example.so.2
Je comprends que l'idée est d'avoir deux fichiers distincts de sorte que deux versions d'une bibliothèque puissent exister sur un système (par opposition à "DLL Hell" sur Windows). Je voudrais savoir comment cela fonctionne dans la pratique? Souvent, je vois que example.so
est en fait un lien symbolique vers example.so.2
où .2
est la dernière version. Comment fonctionne alors une application en fonction d'une ancienne version de example.so
l'identifier correctement? Existe-t-il des règles concernant les numéros à utiliser? Ou est-ce simplement une convention? Est-il vrai que, contrairement à Windows où les binaires logiciels sont transférés entre les systèmes, si un système possède une version plus récente d'un objet partagé, il est automatiquement lié à l'ancienne version lors de la compilation à partir de la source?
Je soupçonne que cela est lié à ldconfig
mais je ne sais pas comment.
Les binaires eux-mêmes savent de quelle version d'une bibliothèque partagée ils dépendent et le demandent spécifiquement. Vous pouvez utiliser ldd
pour afficher les dépendances; les miens pour ls
sont:
$ ldd /bin/ls
linux-gate.so.1 => (0xb784e000)
librt.so.1 => /lib/librt.so.1 (0xb782c000)
libacl.so.1 => /lib/libacl.so.1 (0xb7824000)
libc.so.6 => /lib/libc.so.6 (0xb76dc000)
libpthread.so.0 => /lib/libpthread.so.0 (0xb76c3000)
/lib/ld-linux.so.2 (0xb784f000)
libattr.so.1 => /lib/libattr.so.1 (0xb76bd000)
Comme vous pouvez le voir, cela indique par exemple libpthread.so.0
, pas seulement libpthread.so
.
La raison du lien symbolique est pour l'éditeur de liens. Lorsque vous souhaitez créer un lien contre libpthread.so
directement, vous donnez à gcc
le drapeau -lpthread
, et il ajoute le préfixe lib
et .so
suffixe automatiquement. Vous ne pouvez pas lui dire d'ajouter le .so.0
suffixe, donc le lien symbolique pointe vers la dernière version de la bibliothèque pour faciliter cela
Les nombres dans les bibliothèques partagées sont des conventions utilisées sous Linux pour identifier l'API d'une bibliothèque. Le format est généralement:
libFOO.so.MAJOR.MINOR
Et comme vous l'avez remarqué, il existe généralement un lien symbolique entre libFOO.so et libFOO.so.MAJOR.MINOR. ldconfig est responsable de la mise à jour de ce lien vers la dernière version.
Le MAJOR est généralement incrémenté lorsque l'API change (de nouveaux points d'entrée sont supprimés ou les paramètres ou types modifiés). Le MINEUR est généralement incrémenté pour les versions de correction de bogues ou lorsque de nouvelles API sont introduites sans casser les API existantes.
Une discussion plus approfondie peut être trouvée ici: Dissection des bibliothèques partagées
Les bibliothèques partagées doivent être versionnées selon le schéma suivant:
blah.so.X.Y.Z
où
En général, vous ne voyez que le premier chiffre comme hello.so.1
car le premier chiffre est la seule chose nécessaire pour identifier la "version" de la bibliothèque car tous les autres chiffres sont rétrocompatibles.
ldconfig
conserve un tableau des bibliothèques partagées disponibles sur un système et de l'emplacement du chemin d'accès à cette bibliothèque. Vous pouvez le vérifier en exécutant:
ldconfig -p
Lorsqu'un paquet est construit pour quelque chose comme Red Hat, les bibliothèques partagées appelées dans le binaire seront recherchées et ajoutées en tant que dépendances du paquet au moment de la construction de RPM. Par conséquent, lorsque vous allez installer le package, le programme d'installation recherchera si hello.so.1
est installé sur le système en vérifiant ldconfig
.
Vous pouvez voir les dépendances d'un package en faisant quelque chose comme:
rpm -qpR hello.rpm
Ce système (contrairement à Windows) permet plusieurs versions de hello.so
à installer sur un système et à utiliser simultanément par différentes applications.
libNAME.so est le nom de fichier utilisé par le compilateur/éditeur de liens lors de la première recherche d'une bibliothèque spécifiée par -lNAME. À l'intérieur d'un fichier de bibliothèque partagée se trouve un champ appelé SONAME. Ce champ est défini lorsque la bibliothèque elle-même est liée pour la première fois à un objet partagé (donc) par le processus de génération. Ce SONAME est en fait ce qu'un éditeur de liens stocke dans un exécutable en fonction de cet objet partagé qui lui est lié. Normalement, SONAME se présente sous la forme libNAME.so.MAJOR et est modifié à chaque fois que la bibliothèque devient incompatible avec les exécutables existants qui lui sont liés et que les deux versions principales de la bibliothèque peuvent être maintenues installées selon les besoins (bien qu'une seule sera pointée vers le développement comme libNAME.so) De plus, pour prendre en charge facilement la mise à niveau entre les versions mineures d'une bibliothèque, libNAME.so.MAJOR est normalement un lien vers un fichier comme libNAME.so.MAJOR.MINOR. Une nouvelle version mineure peut être installée et une fois terminée, le lien vers l'ancienne version mineure est renvoyé pour pointer vers la nouvelle version mineure mettant immédiatement à niveau toutes les nouvelles exécutions pour utiliser la bibliothèque mise à niveau. Voir aussi ma réponse à Linux, GNU GCC, ld, scripts de version et format binaire ELF - Comment ça marche?