Wie funktionieren SO-Nummern (Shared Object)?

123

Mir ist bekannt, dass freigegebene Objekte unter Linux "so numbers" verwenden, dh dass verschiedene Versionen eines freigegebenen Objekts unterschiedliche Erweiterungen erhalten, zum Beispiel:

  • example.so.1
  • example.so.2

Ich verstehe die Idee ist, zwei verschiedene Dateien zu haben, so dass zwei Versionen einer Bibliothek auf einem System existieren können (im Gegensatz zu "DLL Hell" unter Windows). Ich möchte wissen, wie das in der Praxis funktioniert? Oft sehe ich , dass example.soin der Tat ist ein symbolischer Link auf , example.so.2wo .2ist die neueste Version. Wie erkennt dann eine Anwendung, die von einer älteren Version example.soabhängt, diese richtig? Gibt es Regeln, welche Zahlen man verwenden muss? Oder ist das einfach Konvention? Ist es der Fall, dass im Gegensatz zu Windows, in dem Software-Binärdateien zwischen Systemen übertragen werden, ein System, das über eine neuere Version eines freigegebenen Objekts verfügt, beim Kompilieren aus dem Quellcode automatisch mit der älteren Version verknüpft wird?

Ich vermute, das hängt damit zusammen, ldconfigaber ich bin mir nicht sicher, wie.

Tshepang
quelle

Antworten:

87

Die Binärdateien wissen selbst, von welcher Version einer gemeinsam genutzten Bibliothek sie abhängig sind, und fordern diese spezifisch an. Mit können Sie ldddie Abhängigkeiten anzeigen. meins für lssind:

$ 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)

Wie Sie sehen können, weist es zB libpthread.so.0nicht nur darauf hin libpthread.so.


Der Grund für den symbolischen Link ist für den Linker. Wenn Sie libpthread.sodirekt mit verknüpfen möchten , geben Sie gccdas Flag an -lpthread, und das libPräfix und .soSuffix werden automatisch hinzugefügt. Sie können ihm nicht sagen, dass er das .so.0Suffix hinzufügen soll , daher verweist der symbolische Link auf die neueste Version der Bibliothek, um dies zu vereinfachen

Michael Mrozek
quelle
Das Gleichheitszeichen "= ls" sollte nicht vorhanden sein. Verwenden Sie einfach "ldd ls"
bmacnaughton
1
@bmacnaughton Das wird wahrscheinlich einen Fehler verursachen, da lddder vollständige Pfad zur ausführbaren Datei erforderlich ist. =lstut das in zsh, aber ich habe es geändert, da nicht jeder diese Shell benutzt
Michael Mrozek
Interessant. Ich starte Bash auf Ubuntu und es scheint ohne den vollständigen Pfad zu funktionieren. Danke für die Erklärung - ich benutze kein zsh.
Bmacnaughton
60

Die Nummern in den gemeinsam genutzten Bibliotheken werden in Linux üblicherweise verwendet, um die API einer Bibliothek zu identifizieren. Normalerweise lautet das Format:

libFOO.so.MAJOR.MINOR

Und wie Sie normalerweise bemerkt haben, gibt es eine symbolische Verknüpfung von libFOO.so zu libFOO.so.MAJOR.MINOR. ldconfig ist dafür verantwortlich, diesen Link auf die neueste Version zu aktualisieren.

Die MAJOR wird normalerweise erhöht, wenn sich die API ändert (neue Einstiegspunkte werden entfernt oder die Parameter oder Typen geändert). Das MINOR wird in der Regel für Fehlerkorrekturversionen oder bei der Einführung neuer APIs erhöht, ohne dass vorhandene APIs beschädigt werden.

Eine ausführlichere Diskussion finden Sie hier: Zerlegen von gemeinsam genutzten Bibliotheken

miguel.de.icaza
quelle
Hallo Miguel, danke dafür, schade, dass ich zwei Antworten nicht akzeptieren kann, da dies die obigen Punkte sehr gut ergänzt. +1 von mir, exzellenter Link auch, nochmals vielen Dank!
4
Das ist fast richtig, aber es ist tatsächlich libFOO.so.MAJOR.MINOR(also nicht am Ende)
JonnyJD
6
Diese Antwort ist so falsch . Erstens haben die Zahlen, die Sie sehen, nichts mit der API zu tun, dies sind reine ABI-Zahlen. Zweitens ist die Konvention hier überhaupt keine semantische Versionierung, wie Sie vorschlagen. Es handelt sich vielmehr um eine Libtool-Konvention, die die nette Eigenschaft hat, einer einzelnen Bibliotheksversionsnummer zuzuordnen, die ld.so vergleichen kann ( weitere Informationen finden Sie unter gnu.org/software/libtool/manual/html_node/… )
NewbiZ
23

Freigegebene Bibliotheken sollten nach folgendem Schema versioniert werden:

blah.so.X.Y.Z

wo

  • X = abwärts inkompatible ABI-Version
  • Y = abwärtskompatible ABI-Version
  • Z = Nur interne Änderungen - keine Änderung des ABI

Normalerweise wird nur die erste Ziffer angezeigt, hello.so.1da nur die erste Ziffer zur Identifizierung der "Version" der Bibliothek erforderlich ist, da alle anderen Ziffern abwärtskompatibel sind.

ldconfigverwaltet eine Tabelle, welche gemeinsam genutzten Bibliotheken auf einem System verfügbar sind und wo sich der Pfad zu dieser Bibliothek befindet. Sie können dies überprüfen, indem Sie Folgendes ausführen:

ldconfig -p

Wenn ein Paket für etwas wie Red Hat erstellt wird, werden die gemeinsam genutzten Bibliotheken, die in der Binärdatei aufgerufen werden, als Abhängigkeiten des Pakets zum Zeitpunkt der RPM-Erstellung gesucht und hinzugefügt. Wenn Sie das Paket installieren, prüft das Installationsprogramm daher, ob hello.so.1es auf dem System installiert ist ldconfig.

Sie können die Abhängigkeiten eines Pakets folgendermaßen anzeigen:

rpm -qpR hello.rpm

Dieses System (im Gegensatz zu Windows) ermöglicht hello.sodie Installation mehrerer Versionen von auf einem System und die gleichzeitige Verwendung durch verschiedene Anwendungen.

Ascotan
quelle
Ich denke das ist die beste Antwort.
Kemin Zhou
1
Gemeinsam genutzte Bibliotheken sollten nach folgendem Schema versioniert werden (…) - Können Sie für diese Anweisung bitte einen Verweis angeben?
Piotr Dobrogost
19

libNAME.so ist der Dateiname, der vom Compiler / Linker verwendet wird, wenn zum ersten Mal nach einer durch -lNAME angegebenen Bibliothek gesucht wird. In einer gemeinsam genutzten Bibliotheksdatei befindet sich ein Feld namens SONAME. Dieses Feld wird festgelegt, wenn die Bibliothek selbst durch den Erstellungsprozess zum ersten Mal mit einem gemeinsam genutzten Objekt verknüpft wird. Dieser SONAME ist tatsächlich das, was ein Linker in einer ausführbaren Datei speichert, abhängig davon, welches gemeinsam genutzte Objekt mit ihm verknüpft ist. Normalerweise hat der SONAME die Form libNAME.so.MAJOR und wird jedes Mal geändert, wenn die Bibliothek mit vorhandenen, damit verknüpften ausführbaren Dateien inkompatibel wird. Beide Hauptversionen der Bibliothek können nach Bedarf installiert bleiben (es wird jedoch nur auf eine Version für die Entwicklung verwiesen) als libNAME.so) Um ein einfaches Upgrade zwischen Nebenversionen einer Bibliothek zu unterstützen, ist libNAME.so.MAJOR normalerweise ein Link zu einer Datei wie libNAME.so.MAJOR.MINOR. Eine neue Unterversion kann installiert werden, und sobald der Link zur alten Unterversion fertiggestellt ist, wird er gestoßen, um auf die neue Unterversion zu verweisen, die alle neuen Ausführungen sofort aktualisiert, um die aktualisierte Bibliothek zu verwenden. Siehe auch meine Antwort aufLinux, GNU GCC, ld, Versionsskripte und das ELF-Binärformat - Wie funktioniert es?

penguin359
quelle