Bibliotecas compartidas: ldd, ldconfig, LD_LIBRARY_PATH
Bibliotecas dinámicas y estáticas
En Linux, el código reutilizable se distribuye como bibliotecas. Las
bibliotecas estáticas (.a) se enlazan al compilar el programa: el código de la
biblioteca queda incorporado en el ejecutable. Las bibliotecas dinámicas o compartidas
(.so, shared object) se cargan en memoria en tiempo de ejecución y pueden ser
compartidas por múltiples programas simultáneamente, ahorrando memoria y facilitando las actualizaciones de
seguridad sin recompilar las aplicaciones.
ldd — Listar dependencias de un binario
ldd muestra las bibliotecas compartidas que necesita un ejecutable y dónde las encuentra el cargador
dinámico.
$ ldd /bin/bash
linux-vdso.so.1 (0x00007ffd3e9d6000)
libtinfo.so.6 => /lib/x86_64-linux-gnu/libtinfo.so.6
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6
/lib64/ld-linux-x86-64.so.2 (0x00007f8b1234a000)
=>→ ruta donde se ha encontrado la bibliotecanot found→ biblioteca no disponible en el sistema
$ ldd /usr/sbin/nginx # dependencias de nginx
$ ldd /usr/bin/python3
ldconfig y /etc/ld.so.conf — El cargador dinámico
El cargador dinámico (ld.so / ld-linux.so) busca las bibliotecas en rutas
predefinidas. La configuración de esas rutas se hace en:
/etc/ld.so.conf→ lista de directorios adicionales/etc/ld.so.conf.d/*.conf→ ficheros adicionales incluidos por el anterior/etc/ld.so.cache→ caché binaria generada porldconfig
Añadir una ruta personalizada de bibliotecas:
# echo "/usr/local/lib/miapp" > /etc/ld.so.conf.d/miapp.conf
# ldconfig # regenerar la caché
Comprobar qué bibliotecas están en caché:
$ ldconfig -p # listar todas las bibliotecas en caché
$ ldconfig -p | grep libssl # filtrar por nombre
Siempre que instales una biblioteca en un directorio no estándar debes ejecutar ldconfig para que los
programas puedan encontrarla.
LD_LIBRARY_PATH y LD_PRELOAD
LD_LIBRARY_PATH
Variable de entorno que añade directorios de búsqueda de bibliotecas con mayor prioridad que los de
/etc/ld.so.conf. Útil para pruebas o entornos de desarrollo.
$ export LD_LIBRARY_PATH=/usr/local/lib/miapp:$LD_LIBRARY_PATH
$ ./mi-programa # usa primero las bibliotecas de la ruta añadida
# Uso puntual sin modificar el entorno permanente:
$ LD_LIBRARY_PATH=/tmp/libs ./mi-programa
No uses LD_LIBRARY_PATH permanentemente en producción; es una fuente de problemas difíciles de depurar.
Usa /etc/ld.so.conf.d/ + ldconfig en su lugar.
LD_PRELOAD
Fuerza la carga de una biblioteca antes que cualquier otra, incluyendo las del sistema. Útil para sustituir funciones puntualmente.
$ LD_PRELOAD=/usr/lib/x86_64-linux-gnu/libfakeroot/libfakeroot-tcp.so fakeroot
Ejemplo práctico completo
Compilar una biblioteca y registrarla en el sistema:
# 1. Compilar la biblioteca compartida
$ gcc -shared -fPIC -o libhola.so hola.c
# 2. Copiarla al directorio de bibliotecas del sistema
# cp libhola.so /usr/local/lib/
# 3. Registrar el directorio en el cargador dinámico
# echo "/usr/local/lib" > /etc/ld.so.conf.d/local.conf
# ldconfig
# 4. Verificar que está disponible
$ ldconfig -p | grep libhola
libhola.so => /usr/local/lib/libhola.so
# 5. Compilar y ejecutar un programa que la use
$ gcc -o programa main.c -lhola
$ ldd ./programa | grep libhola
libhola.so => /usr/local/lib/libhola.so