Come funzionano i numeri SO (oggetto condiviso)?


123

Sono consapevole che gli oggetti condivisi su Linux usano "così numeri", vale a dire che alle diverse versioni di un oggetto condiviso vengono assegnate estensioni diverse, ad esempio:

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

Capisco l'idea è di avere due file distinti in modo tale che su un sistema possano esistere due versioni di una libreria (al contrario di "DLL Hell" su Windows). Mi piacerebbe sapere come funziona in pratica? Spesso, vedo che example.soin realtà è un collegamento simbolico a example.so.2dove .2è l'ultima versione. In che modo quindi un'applicazione che dipende da una versione precedente di example.soidentificarla correttamente? Ci sono delle regole su quali numeri si devono usare? O è semplicemente una convenzione? È vero che, a differenza di Windows in cui i file binari del software vengono trasferiti tra sistemi, se un sistema ha una versione più recente di un oggetto condiviso, viene automaticamente collegato alla versione precedente durante la compilazione dal sorgente?

Ho il sospetto che questo sia legato ldconfigma non sono sicuro di come.

Risposte:


87

I binari stessi sanno da quale versione di una libreria condivisa dipendono e la richiedono in modo specifico. È possibile utilizzare lddper mostrare le dipendenze; i miei per lssono:

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

Come puoi vedere, indica ad esempio libpthread.so.0, non solo libpthread.so.


Il motivo del collegamento simbolico è per il collegamento. Quando vuoi collegarti libpthread.sodirettamente, dai gccil flag -lpthreade questo si aggiunge automaticamente al libprefisso e al .sosuffisso. Non puoi dirlo per aggiungere il .so.0suffisso, quindi il link simbolico punta alla versione più recente della lib per facilitare che


Il segno uguale "= ls" non dovrebbe essere presente. Basta usare "ldd ls"
bmacnaughton il

1
@bmacnaughton Questo probabilmente ti darà un errore perché lddrichiede il percorso completo dell'eseguibile. =lslo fa in zsh, ma l'ho cambiato poiché non tutti usano quella shell
Michael Mrozek

Interessante. Sto eseguendo bash su Ubuntu e sembra funzionare senza il percorso completo. Grazie per la spiegazione - non uso zsh.
bmacnaughton,

60

I numeri nelle librerie condivise sono convenzioni utilizzate in Linux per identificare l'API di una libreria. In genere il formato è:

libFOO.so.MAJOR.MINOR

E come hai notato di solito c'è un collegamento simbolico da libFOO.so a libFOO.so.MAJOR.MINOR. ldconfig è responsabile dell'aggiornamento di questo collegamento alla versione più recente.

Il MAJOR viene in genere incrementato quando l'API cambia (i nuovi punti di ingresso vengono rimossi o i parametri o i tipi cambiati). Il MINOR viene in genere incrementato per le versioni di correzione dei bug o quando vengono introdotte nuove API senza interrompere le API esistenti.

Una discussione più ampia può essere trovata qui: Analizzare le librerie condivise


Ciao Miguel, grazie per questo, peccato non posso accettare due risposte perché ciò integra bene quanto sopra. +1 da parte mia, ottimo anche il link, grazie ancora!

4
È quasi corretto, ma in realtà libFOO.so.MAJOR.MINOR(quindi non alla fine)
JonnyJD

6
Questa risposta è così sbagliata . Innanzitutto, i numeri che vedi non hanno nulla a che fare con l'API, questi sono puramente ABI. In secondo luogo, la convenzione qui non è TUTTA la versione semantica come suggerisce la risposta. Piuttosto è una convenzione libtool che ha la bella proprietà di mappare su un singolo numero di versione della libreria che ld.so può anche confrontare (vedi gnu.org/software/libtool/manual/html_node/… per maggiori informazioni)
NewbiZ

23

Le librerie condivise devono essere controllate in base al seguente schema:

blah.so.X.Y.Z

dove

  • X = versione ABI all'indietro incompatibile
  • Y = versione ABI retrocompatibile
  • Z = Solo modifiche interne - nessuna modifica all'ABI

In genere vedi solo la prima cifra come hello.so.1perché la prima cifra è l'unica cosa necessaria per identificare la "versione" della libreria poiché tutte le altre cifre sono retrocompatibili.

ldconfigmantiene una tabella di quali librerie condivise sono disponibili su un sistema e dove esiste il percorso di quella libreria. Puoi verificarlo eseguendo:

ldconfig -p

Quando un pacchetto viene creato per qualcosa come Red Hat, le librerie condivise richiamate nel file binario verranno cercate e aggiunte come dipendenze del pacchetto al momento della creazione di RPM. Pertanto, quando si va a installare il pacchetto, il programma di installazione cercherà se hello.so.1è installato o meno sul sistema controllando ldconfig.

Puoi vedere le dipendenze di un pacchetto facendo qualcosa del tipo:

rpm -qpR hello.rpm

Questo sistema (a differenza di Windows) consente di hello.soinstallare più versioni del sistema su un sistema e di essere utilizzate contemporaneamente da diverse applicazioni.


Penso che questa sia la risposta migliore.
Kemin Zhou,

1
Le librerie condivise dovrebbero essere sottoposte a versione secondo il seguente schema (...) - Potresti fornire un riferimento per questa affermazione?
Piotr Dobrogost,

19

libNAME.so è il nome file utilizzato dal compilatore / linker alla prima ricerca di una libreria specificata da -lNAME. All'interno di un file di libreria condiviso è presente un campo chiamato SONAME. Questo campo viene impostato quando la libreria stessa viene collegata per la prima volta a un oggetto condiviso (quindi) dal processo di compilazione. Questo SONAME è in realtà ciò che un linker memorizza in un eseguibile a seconda dell'oggetto condiviso a cui è collegato. Normalmente SONAME ha la forma di libNAME.so.MAJOR e viene modificato ogni volta che la libreria diventa incompatibile con gli eseguibili esistenti collegati ad essa ed entrambe le principali versioni della libreria possono essere mantenute installate secondo necessità (anche se solo una verrà indicata per lo sviluppo come libNAME.so) Inoltre, per supportare facilmente l'aggiornamento tra le versioni secondarie di una libreria, libNAME.so.MAJOR è normalmente un collegamento a un file come libNAME.so.MAJOR.MINOR. È possibile installare una nuova versione secondaria e, una volta completata, il collegamento alla vecchia versione secondaria viene interrotto per puntare alla nuova versione secondaria che aggiorna immediatamente tutte le nuove esecuzioni per utilizzare la libreria aggiornata. Inoltre, vedi la mia risposta aLinux, GNU GCC, ld, script di versione e formato binario ELF - Come funziona?

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.