Comment fonctionnent les numéros SO (objets partagés)?


124

Je suis conscient que les objets partagés sous Linux utilisent "so numbers", à savoir que différentes versions d'un objet partagé ont 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" sous Windows). Je voudrais savoir comment cela fonctionne dans la pratique? Souvent, je vois example.soest en fait un lien symbolique vers example.so.2.2est la dernière version. Comment alors une application dépendant d'une ancienne version de l' example.soidentifie-t-elle 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 fichiers binaires logiciels sont transférés entre systèmes, si un système a une version plus récente d'un objet partagé, il est automatiquement lié à l'ancienne version lors de la compilation à partir du source?

Je soupçonne que cela est lié à, ldconfigmais je ne sais pas comment.

Réponses:


88

Les binaires eux-mêmes savent de quelle version d'une bibliothèque partagée ils dépendent et en font la demande spécifique. Vous pouvez utiliser lddpour afficher les dépendances. les miens lssont:

$ 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 constater, 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 libpthread.socréer un lien direct, vous attribuez gccle drapeau -lpthread, qui ajoute automatiquement le libpréfixe et le .sosuffixe. Vous ne pouvez pas lui dire d’ajouter le .so.0suffixe, le lien symbolique pointe donc sur la version la plus récente de la bibliothèque pour faciliter ce travail.


Le signe égal "= ls" ne doit pas être présent. Il suffit d'utiliser "ldd ls"
bmacnaughton

1
@bmacnaughton Cela vous donnera probablement une erreur car lddnécessite le chemin complet de l'exécutable. =lsfait ça en zsh, mais je l’ai changé puisque tout le monde n’utilise pas ce shell
Michael Mrozek

Intéressant. J'exécute bash sur Ubuntu et cela semble fonctionner sans le chemin d'accès complet. Merci pour l'explication - je n'utilise pas zsh.
bmacnaughton

60

Les numéros dans les bibliothèques partagées sont une convention utilisée sous Linux pour identifier l'API d'une bibliothèque. Typiquement le format est:

libFOO.so.MAJOR.MINOR

Et comme vous l'avez remarqué d'habitude, il existe un lien symbolique de libFOO.so à libFOO.so.MAJOR.MINOR. ldconfig est responsable de la mise à jour de ce lien vers la version la plus récente.

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 sont modifiés). MINOR est généralement incrémenté pour les versions de correctifs de bogues ou lors de l'introduction de nouvelles API sans rompre les API existantes.

Vous trouverez une discussion plus approfondie ici: Dissection de bibliothèques partagées


Bonjour Miguel, merci pour cela, dommage que je ne puisse pas accepter deux réponses car cela complète bien ce qui précède. +1 de moi, excellent lien aussi, merci encore!

4
C'est presque correct, mais c'est en fait libFOO.so.MAJOR.MINOR(donc pas à la fin)
JonnyJD

6
Cette réponse est tellement fausse . Tout d'abord, les chiffres que vous voyez n'ont rien à voir avec l'API, ils sont purement ABI. Deuxièmement, la convention ici n’est pas du tout un versioning sémantique comme vous le suggérez. C'est plutôt une convention libtool qui a la propriété intéressante de mapper sur un numéro de version de bibliothèque que ld.so peut comparer (voir gnu.org/software/libtool/manual/html_node/… pour plus d'informations)
NewbiZ

23

Les bibliothèques partagées doivent être versionnées selon le schéma suivant:

blah.so.X.Y.Z

  • X = version ABI incompatible avec les versions antérieures
  • Y = version ABI à compatibilité ascendante
  • Z = modifications internes uniquement - aucune modification de l’ABI

En règle générale, vous ne voyez que le premier chiffre comme hello.so.1parce que le premier chiffre est la seule chose nécessaire pour identifier la "version" de la bibliothèque puisque tous les autres chiffres sont compatibles avec les versions antérieures.

ldconfiggère un tableau des bibliothèques partagées disponibles sur un système et indiquant le chemin d'accès à cette bibliothèque. Vous pouvez le vérifier en lançant:

ldconfig -p

Lorsqu'un package est créé pour quelque chose comme Red Hat, les bibliothèques partagées appelées dans le fichier binaire sont recherchées et ajoutées en tant que dépendances du package au moment de la compilation de RPM. Par conséquent, lorsque vous allez installer le paquet, le programme d'installation recherchera si oui ou non hello.so.1est installé sur le système en vérifiant ldconfig.

Vous pouvez voir les dépendances d'un paquet en faisant quelque chose comme:

rpm -qpR hello.rpm

Ce système (contrairement à Windows) permet d' hello.soinstaller plusieurs versions du sur un système et de les utiliser simultanément par différentes applications.


Je pense que c'est la meilleure réponse.
Kemin Zhou

1
Les bibliothèques partagées doivent être versionnées selon le schéma suivant (…) - Pourriez-vous fournir une référence pour cette déclaration?
Piotr Dobrogost

19

libNAME.so est le nom de fichier utilisé par le compilateur / éditeur de liens lors de la recherche initiale d'une bibliothèque spécifiée par -lNAME. Dans 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é (so) par le processus de construction. Ce SONAME est en réalité ce qu'un éditeur de liens stocke dans un exécutable en fonction du lien entre l'objet partagé et l'objet lié. En règle générale, SONAME se présente sous la forme libNAME.so.MAJOR et est modifié à chaque fois que la bibliothèque devient incompatible avec les fichiers exécutables existants qui lui sont liés et que les deux versions principales de la bibliothèque peuvent être conservées installées si nécessaire (un seul d'entre eux sera désigné pour 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 tel que 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 modifié pour pointer vers la nouvelle version mineure en mettant immédiatement à niveau toutes les nouvelles exécutions pour utiliser la bibliothèque mise à niveau. Voir aussi ma réponse àLes scripts Linux, GNU GCC, ld, version et le format binaire ELF - Comment ça marche?

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.