%3F.png)
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.so
en realidad es un enlace simbólico hacia example.so.2
dónde .2
está la última versión. ¿Cómo entonces una aplicación que depende de una versión anterior example.so
la identifica correctamente? ¿Existe alguna regla sobre qué números se deben usar? ¿O se trata simplemente de una convención? ¿Es cierto que, a diferencia de Windows, donde los 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 al compilar desde la fuente?
Sospecho que esto está relacionado, ldconfig
pero no estoy seguro de cómo.
Respuesta1
Los propios binarios saben de qué versión de una biblioteca compartida dependen y la solicitan específicamente. Puede utilizar ldd
para mostrar las dependencias; los míos ls
son:
$ 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 a, por ejemplo libpthread.so.0
, no solo libpthread.so
.
El motivo del enlace simbólico es el enlazador. Cuando desea vincular libpthread.so
directamente, le da gcc
la bandera -lpthread
y agrega el lib
prefijo y .so
el sufijo automáticamente. No puede decirle que agregue el .so.0
sufijo, por lo que el enlace simbólico apunta a la versión más reciente de la biblioteca para facilitarlo.
Respuesta2
Los números en las bibliotecas compartidas son una convención utilizada en Linux para identificar la API de una biblioteca. Normalmente el formato es:
libFOO.so.MAJOR.MINOR
Y como habrás notado, normalmente 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 MAJOR normalmente se incrementa cuando cambia la API (se eliminan nuevos puntos de entrada o se cambian los parámetros o tipos). El valor MINOR normalmente se incrementa cuando se publican correcciones de errores o cuando se introducen nuevas API sin alterar las API existentes.
Puede encontrar una discusión más extensa aquí:Diseccionando bibliotecas compartidas
Respuesta3
Las bibliotecas compartidas deben versionarse según 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 el ABI
Por lo general, solo ve el primer dígito hello.so.1
porque 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.
ldconfig
mantiene una tabla de qué bibliotecas compartidas están disponibles en un sistema y dónde existe la ruta a esa biblioteca. Puedes verificar esto ejecutando:
ldconfig -p
Cuando se crea un paquete para algo como Red Hat, las bibliotecas compartidas que se llaman 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.1
está instalado o no en el sistema marcando ldconfig
.
Puedes ver las dependencias de un paquete haciendo algo como:
rpm -qpR hello.rpm
Este sistema (a diferencia de Windows) permite hello.so
instalar múltiples versiones de en un sistema y ser utilizadas por diferentes aplicaciones al mismo tiempo.
Respuesta4
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 se vincula por primera vez a un objeto compartido mediante el proceso de compilación. Este SONAME es en realidad lo que un vinculador almacena en un ejecutable dependiendo del objeto compartido que esté vinculado con él. Normalmente, SONAME tiene el formato libNAME.so.MAJOR y se cambia cada vez que la biblioteca se vuelve incompatible con los ejecutables existentes vinculados a ella 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 fácil actualización entre versiones menores de una biblioteca, libNAME.so.MAJOR normalmente es 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 elimina para apuntar a la nueva versión secundaria, actualizando inmediatamente todas las ejecuciones nuevas para usar la biblioteca actualizada. Además, vea mi respuesta aLinux, GNU GCC, ld, scripts de versión y formato binario ELF: ¿cómo funciona?