LPIC-1 102.3: gestión de bibliotecas compartidas

Seguimos con la serie LPIC-1, concretamente con el tema 102.3 referente a la gestión de bibliotecas compartidas. Ya deberías saber que en GNU/Linux, como en otros sistemas operativos, existen bibliotecas que son usadas por los programas. Son una dependencia particular. Si sigues el hilo de artículos de la serie Programación, sabrás más o menos lo que es una biblioteca. No obstante, en próximas entradas de esa serie se tratarán en profundidad.

Puedes verlas como si fuese bloques prefabricados que contienen funciones o partes de código fuente que se usan de forma frecuente. De ese modo, el programador no tiene que escribirlas desde cero, sino que simplemente hace una llamada a esa biblioteca y puede usar las funciones en su código.

¿Dónde están?

Bueno, debes saber que existen bibliotecas compartidas y estáticas. Las estáticas son compiladas junto al código fuente del programa y por tanto el binario o ejecutable las contiene. En cambio, algunas son comunes a más programas y para ahorrar espacio en memoria se pueden sacar del binario y hacer que se usen cuando sean necesarias. Éstas últimas serían las compartidas.

Un ejemplo sencillo. Imagina una biblioteca A indefinida. Y también imagina que tienes un binario X y otro Y. Si ambos binarios necesitan esa biblioteca y la usamos como estática, el binario tendría un peso de (X+A)+(Y+A) en la memoria. En cambio, si se tratase como compartida solo tendrías en memoria de X+Y+A, puesto que solo se debería cargar una vez. No obstante, no todo son desventajas para las estáticas, ya que al estar integradas generan un ejecutable autónomo.

Entendiendo eso, sabrás que las estáticas vienen ya incluidas con los paquetes que tengas instalados. Mientras que las compartidas se alojan en:

  • /lib
  • /lib64
  • /include
  • /usr/lib
  • /usr/local/lib
  • etc.

En Linux, las compartidas tendrán un nombre tipo *.so.version. Mientras que las estáticas son *.a. SO es de Shared Object, y un ejemplo podría ser libc.so.0. En cuanto a la estática, por ejemplo puedes tener libYARP_dev.a.

Puedes ver las rutas si usas la variable de entorno LD_LIBRARY_PATH. Con ella también podrías incluso agregar una nueva ruta por si necesitas incluir una biblioteca compartida que esté en una ruta rara.

Debes saber también que Linux tiene un dynamic-loader para buscarlas y cargarlas cuando son requeridas estas bibliotecas compartidas. Se conoce como ld-linux.so y ld.so. Gracias a las reseñas que el binario le pasa, podrá hacer su trabajo. Pero necesitan que actualices la cache con ldconfig, de lo contrario no podrán localizar bibliotecas nuevas o cambios…

Gestión de bibliotecas compartidas

Existe un comando con el que puedes conocer las dependencias de bibliotecas que tiene un binario. Por ejemplo, puedes averiguar de qué bibliotecas depende bash con:

ldd /bin/bash

Es decir, es el comando seguido de la ruta completa del binario. Si no sabes dónde se encuentra el binario, ya sabes que puedes usar which para localizarlo:

which bash

Cuando algún programa tiene problemas con una biblioteca compartida, tipo error while loading shared libraries: nombre_libreria: cannot open shared object file: No such file or directory, puedes resolverlo fácilmente. Si te fijas en nombre_liberaria que muestra el error, sabrás de qué biblioteca se trata, es posible que no esté instalada en tu sistema, en cuyo caso debes instalarla, o que se encuentre en una ruta errónea. En éste último caso puedes usar las herramientas de búsqueda para localizarla. Luego puedes especificar la ruta en la variable de entorno o desplazarla a una ruta conocida…

En otras ocasiones puede que el problema radique en el nombre de la biblioteca. Por ejemplo, si un programa está haciendo referencia a library-x.so.5.7 y en tu sistema aparece como library-x.so, no se podrá identificar correctamente, generando el error. En este caso, la solución es crear un enlace simbólico y luego actualizar los enlaces del sistema con ldconfig:

ln -s library-x-so library-x.so.5.7
ldconfig

Nunca debes modificar el nombre de una biblioteca, o podría resolver tu problema y generar otros tantos…

En caso de una actualización de una biblioteca, eso también podría generar problemas en programas dependientes. Para realizar una actualización correcta debes descargar la nueva versión, alojarla en la ruta adecuada, generar el enlace simbólico con ambas versiones y actualizar cache. Por ejemplo, imagina que quieres actualizar libncurses de la 5.0 a la 5.7 (una vez has descargado libncurses.a y libncurses.so.5.7):

cp libncurses.a /usr/lib
cp libncurses.so.5.7 /lib
ln -sf /lib/libncurses.so.5.7 /lib/libncurses.so.5
ldconfig

La importancia de actualizar siempre la cache es que el gestor de Linux no lee siempre /etc/ld.so.conf (ahora encontrarás /etc/ld.so.conf.d/ y dentro diveros ficheros de configuración que puedes modificar para agregar rutas, etc. Es un proceso fácil, puedes agregar la ruta que quieras de forma simple), sino que leen un binario llamado /etc/ld.so.cache. De hecho, cuando usas gestores de paquetes, tras la instalación de paquetes suelen hacer un ldconfig automático.

Y por último, recuerda que puedes agregar rutas exóticas a tu variable de entorno con:

export LD_LIBRARY_PATH = /tu/nueva/ruta

Isaac

Apasionado de la computación y la tecnología en general. Siempre intentando desaprender para apreHender.

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

A %d blogueros les gusta esto:

Si continuas utilizando este sitio aceptas el uso de cookies. más información

Los ajustes de cookies de esta web están configurados para "permitir cookies" y así ofrecerte la mejor experiencia de navegación posible. Si sigues utilizando esta web sin cambiar tus ajustes de cookies o haces clic en "Aceptar" estarás dando tu consentimiento a esto.

Cerrar