¿Cómo funcionan los números SO (objeto compartido)?


123

Soy consciente de que los objetos compartidos en Linux usan "números", es decir, que las diferentes versiones de un objeto compartido reciben diferentes extensiones, por ejemplo:

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

Entiendo que la idea es tener dos archivos distintos de modo que puedan existir dos versiones de una biblioteca en un sistema (a diferencia de "DLL Hell" en Windows). ¿Me gustaría saber cómo funciona esto en la práctica? A menudo, veo que example.sode hecho es un enlace simbólico a example.so.2dónde .2está la última versión. ¿Cómo, entonces, una aplicación que depende de una versión anterior la example.soidentifica correctamente? ¿Hay alguna regla sobre qué números se deben usar? ¿O es simplemente una convención? ¿Es el caso que, a diferencia de Windows donde los archivos binarios de software se transfieren entre sistemas, si un sistema tiene una versión más nueva de un objeto compartido, se vincula automáticamente a la versión anterior cuando se compila desde la fuente?

Sospecho que esto está relacionado, ldconfigpero no estoy seguro de cómo.

Respuestas:


87

Los propios binarios saben de qué versión de una biblioteca compartida dependen y lo solicitan específicamente. Puede usar lddpara mostrar las dependencias; los míos lsson:

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

Como puede ver, apunta, por ejemplo libpthread.so.0, no solo libpthread.so.


La razón del enlace simbólico es para el enlazador. Cuando desea vincular libpthread.sodirectamente, le da gccla bandera -lpthread, y agrega el libprefijo y el .sosufijo automáticamente. No puede decirle que agregue el .so.0sufijo, por lo que el enlace simbólico apunta a la versión más reciente de la biblioteca para facilitar que


El signo igual "= ls" no debe estar presente. Simplemente use "ldd ls"
bmacnaughton

1
@bmacnaughton Eso probablemente le dará un error porque lddrequiere la ruta completa al ejecutable. =lshace eso en zsh, pero lo cambié ya que no todos usan ese shell
Michael Mrozek

Interesante. Estoy ejecutando bash en Ubuntu y parece funcionar sin la ruta completa. Gracias por la explicación: no uso zsh.
bmacnaughton

60

Los números en las bibliotecas compartidas son convenciones utilizadas en Linux para identificar la API de una biblioteca. Por lo general, el formato es:

libFOO.so.MAJOR.MINOR

Y como notó, generalmente hay un enlace simbólico de libFOO.so a libFOO.so.MAJOR.MINOR. ldconfig es responsable de actualizar este enlace a la versión más reciente.

El MAYOR generalmente se incrementa cuando cambia la API (se eliminan nuevos puntos de entrada o se cambian los parámetros o tipos). El MENOR generalmente se incrementa para versiones de corrección de errores o cuando se introducen nuevas API sin romper las API existentes.

Una discusión más extensa se puede encontrar aquí: Disección de bibliotecas compartidas


Hola Miguel, gracias por eso, lástima, no puedo aceptar dos respuestas porque eso complementa muy bien lo anterior. +1 de mi parte, excelente enlace también, ¡gracias de nuevo!

44
Eso es casi correcto, pero en realidad lo es libFOO.so.MAJOR.MINOR(así que no al final)
JonnyJD

66
Esta respuesta es muy incorrecta . Primero, los números que ves no tienen nada que ver con la API, estos son puramente ABI. En segundo lugar, la convención aquí no es la versión semántica en absoluto como su respuesta sugiere. Más bien es una convención de libtool que tiene la buena propiedad de mapear a un solo número de versión de biblioteca que ld.so puede comparar (ver gnu.org/software/libtool/manual/html_node/… para más información)
NewbiZ

23

Las bibliotecas compartidas deben versionarse de acuerdo con el siguiente esquema:

blah.so.X.Y.Z

dónde

  • X = versión ABI incompatible con versiones anteriores
  • Y = versión ABI compatible con versiones anteriores
  • Z = Solo cambios internos: sin cambios en la ABI

Normalmente, solo se ve el primer dígito hello.so.1porque el primer dígito es lo único que se necesita para identificar la "versión" de la biblioteca, ya que todos los demás dígitos son compatibles con versiones anteriores.

ldconfigmantiene una tabla de qué bibliotecas compartidas están disponibles en un sistema y dónde existe la ruta a esa biblioteca. Puede verificar esto ejecutando:

ldconfig -p

Cuando se crea un paquete para algo como Red Hat, las bibliotecas compartidas que se invocan en el binario se buscarán y agregarán como dependencias del paquete en el momento de la compilación de RPM. Por lo tanto, cuando vaya a instalar el paquete, el instalador buscará si hello.so.1está instalado o no en el sistema mediante una comprobación ldconfig.

Puede ver las dependencias de un paquete haciendo algo como:

rpm -qpR hello.rpm

Este sistema (a diferencia de Windows) permite hello.soque se instalen múltiples versiones del mismo en un sistema y que sean utilizadas por diferentes aplicaciones al mismo tiempo.


Creo que esta es la mejor respuesta.
Kemin Zhou

1
Las bibliotecas compartidas deben versionarse de acuerdo con el siguiente esquema (...) . ¿Podría proporcionarnos referencia para esta declaración?
Piotr Dobrogost

19

libNAME.so es el nombre de archivo utilizado por el compilador / enlazador cuando busca por primera vez una biblioteca especificada por -lNAME. Dentro de un archivo de biblioteca compartida hay un campo llamado SONAME. Este campo se establece cuando la biblioteca misma se vincula por primera vez a un objeto compartido (así) mediante el proceso de compilación. Este SONAME es en realidad lo que un vinculador almacena en un ejecutable dependiendo de que el objeto compartido esté vinculado con él. Normalmente, el SONAME tiene la forma de libNAME.so.MAJOR y se cambia cada vez que la biblioteca se vuelve incompatible con los ejecutables existentes vinculados a él y ambas versiones principales de la biblioteca se pueden mantener instaladas según sea necesario (aunque solo se señalará una para el desarrollo como libNAME.so) Además, para permitir una actualización sencilla entre versiones menores de una biblioteca, libNAME.so.MAJOR es normalmente un enlace a un archivo como libNAME.so.MAJOR.MINOR. Se puede instalar una nueva versión secundaria y una vez completada, el enlace a la versión secundaria anterior se abre para señalar a la nueva versión secundaria que actualiza inmediatamente todas las nuevas ejecuciones para usar la biblioteca actualizada. Además, vea mi respuesta aLinux, GNU GCC, ld, scripts de versión y el formato binario ELF - ¿Cómo funciona?

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.