Aprende GNU/Linux, Programación 7

Las librerías compartidas en Linux, que son y como gestionarlas

Antes de empezar la explicación sobre las librerías compartidas creo que es conveniente definir bien lo que es una librería y los tipos de librerías que hay. Una librería es un fichero que contiene un conjunto de funciones, escritas en un lenguaje de programación, para ser utilizadas por un programa, de forma que si un programa necesita usar estas funcionalidades puede acceder a la librería sin tener que reescribir el código. La diferencia entre un programa y una librería es mínima, la única diferencia es que una librería no se ejecuta de forma autónoma ( no contiene el bloque de instrucción main ), pero por lo demás funciona como un programa normal ( también puede requerir de otras librerías para funcionar).

Tipos de librerías

Existen dos tipos de librerías, las librerías compartidas o dinámicas y las librerías estáticas. La diferencia entre ambas es que mientras en las librerías compartidas el acceso es dinámico y se realiza en tiempo de ejecución, en las estáticas las funcionalidades son enlazadas en tiempo de compilación y sustituidas por la llamada en el fichero ejecutable final.

Esquema sobre las librerias en Linux
Un conjunto de funciones propuestas por una o varias librerías forma una API ( application programming Interface) y estas se pueden agrupar en un framework que ofrece una solución completa para un dominio dado.
APIs y Frameworks

Las librerías compartidas

En este articulo vamos a tratar las librerías compartidas, y mas específicamente sobre las de Linux. En Linux ( y en Unix ) las librerías compartidas se llaman Shared Objects y llevan el sufijo .so ( su equivalente en Windows son las .dll ).

Como ya hemos mencionado, las librerías compartidas se vinculan a un programa en tiempo de ejecución, permitiendo que el código de la librería se cargue en memoria una única vez y pueda ser usado por varios programas, de esta forma se consigue que el tamaño del código sea menor con su correspondiente ahorro de espacio en memoria.

Ademas de esto con las librerías compartidas se cumple el principio de modularidad ( programación modular o orientada a objetos ), de forma que si necesitamos modificar alguna funcionalidad nos bastara con editar la librería que la contiene, dejando el programa que las utiliza sin modificar.

Los nombres de las librerías compartidas

Por convenio las librerías compartidas pueden tener varios tipos de nombre :

El nombre usado por el enlazador (‘lib’ + nombre de la libreria + ‘.so’)

Nombre completo (‘lib’ + nombre de la libreria + ‘.so’ + ‘.’ + numero de versión) // Link hacia la librería con el nombre real

Nombre real (‘lib’ + nombre de la libreria + ‘.so’ + ‘.’ + numero de versión + ‘.’ + numero de subversión + ‘.’ + revisión ) // La revisión es opcional

Para el cambio de versiones hay que tener dos factores en cuenta, el numero de la subversión se cambia cuando se realizan cambios en la librería y esta no pierde compatibilidad con la version anterior, pero si se pierde compatibilidad el cambio tiene que ser de versión y no de subversión. Gracias a este convenio de nombres es posible que múltiples versiones de una librería compartida coexistan en el sistema.

¿Dónde se encuentran dentro de la jerarquía de ficheros?

En el articulo Gestión de ficheros en Linux para dummies hablamos sobre la jerarquía de ficheros en Linux, en esta jerarquía existen lugares en los que se almacenan este tipo de librerías. Las librerías compartidas se colocan en directorios denominados lib:

– /lib : Librerías de sistema, vitales

– /usr/lib : Librerías de usuario básicas, no se necesitan en el boot

– /usr/local/lib : Librerías que no forman parte de la distribución estándar

La librería mas importante del sistema es la de C. Todos los programas compilados son vinculados a libc, por lo que mejor no borres esta libreria, a no ser que quieras que el sistema deje de funcionar.

¿Que librerías tiene vinculadas un programa?

Gracias al comando ldd podemos conocer las librerías vinculadas a un programa. Como parámetro tenemos que pasar la ubicación del programa.

Por ejemplo si queremos conocer las librerías asociadas al editor de texto Gedit el comando seria el siguiente :

 ldd /usr/bin/gedit

El comando ldd también nos indicara si falta alguna librería asociada.

Añadiendo nuevas librerías

Para añadir una nueva librería, tenemos que ubicarla en uno de los directorios mencionados y después ejecutar el programa ldconfig. ldconfig se va a encargar de dejar la librería accesible para el enlazador, creando los vínculos y caché necesarios en el archivo /etc/ld.so.conf, y en los directorios de confianza (/lib y /usr/lib).

Si se da el caso que la ubicación de la librería no es una de las estándares ( las mencionadas ), sera necesario agregar el directorio a /etc/ld.so.conf.

El enlazador dinámico ld.so

Ya hemos dicho que los ficheros binarios en Linux requieren un enlace dinámico ( a no ser que se opte por el enlace estático ), y de este enlace se encargan los programas ld.so y ld-linux.so*. La misión de estos dos es encontrar y cargar las bibliotecas compartidas requeridas por el programa en cuestión, preparar el programa para ejecutarse y ejecutarlo. Para ello el binario en cuestión ofrece el nombre de las bibliotecas que necesita y ld.so se encarga de buscarlas en las siguientes ubicaciones :

– Las definidas a través de la variable de entorno LD_LIBRARY_PATH. Salvo cuando el ejecutable tiene activo el bit setuid/setgid, en cuyo caso se ignora.

– Las definidas en el propio binario.

– En el fichero /etc/ld.so.cache, que contiene una lista compilada de bibliotecas candidatas encontradas previamente en la ruta de bibliotecas ampliada.

– En la ruta predeterminada /lib, y despues en /usr/lib/. Si el binario fue enlazado con la opción -znodeflib, se omite este paso.

La primera librería encontrada que cumpla la dependencia será la utilizada. Hay que tener en cuenta que lo que el binario contiene no es una lista con los enlaces a cada librería, sino una lista de rutas adicionales en las que buscar las dependencias ( si las tiene ).

¡Espero que os sirva de ayuda esta explicación sobre las librerías compartidas en Linux! Si quieres aprender a crear y ligar no dejes de visitar el articulo sobre Creación de librerías estáticas y compartidas en Linux con gcc

 

Sobre el autor / 

AsierPH

Entusiasta de las tecnologías libres y fundador de OvToaster.com | “Las obras de conocimiento deben ser libres, no hay excusas para que no sea así“

Articulos relacionados

7 comentarios

  1. María José 17 enero, 2017 at 8:29 am -  Responder

    Muy bien explicado, claro y conciso.

  2. wsn 27 agosto, 2015 at 9:42 am -  Responder

    Hola!

    Estupenda explicación ASIERPH, se agradece y mucho artículos como este donde se explica las nociones relativas a estos temas de una manera tan asequible.

    Gracias por compartir conocimientos con calidad y gracias también por no obligarme postear esto, entrando en la cuenta de gmail, facebook o similares,

    Gracias!

    • AsierPH 27 agosto, 2015 at 10:14 am -  Responder

      Buenas Wsn,
      Muchas gracias por el comentario, me alegra mucho que te sea útil.
      A mi también me fastidia mucho tener que andar metiendo mis cuentas en todas partes, por lo que, habría sido incongruente añadirlo en mi blog 🙂
      Un saludo!

  3. Kintxo 14 agosto, 2015 at 9:32 pm -  Responder

    Hola Asier, estoy interesado recopilar y adaptar librerías que hacen cálculos geométricos en C. Voy descubriendo poco a poco y no sin dificultades la herramienta make. Creo que empiezo a entender la esencia del sistema de hilos de Unix y he disfrutado leyendo tu explicación, gracias.

    Cuando hablas de las opciones de búsqueda que utilizan ld.so y ld-linux.so* para encontrar la ruta de la biblioteca ejecutable entiendo se puede ‘informar’ al programa de la ruta donde encontrará las librerías de cuatro formas y que por eso en los diferentes tutoriales que estoy leyendo cada uno lo haga de una forma.

    Hago un copypaste porque me gustaría consultarte acerca de las opciones para saber cuál es la que más piensas que me puede convenir

    – Las definidas a través de la variable de entorno LD_LIBRARY_PATH. Salvo cuando el ejecutable tiene activo el bit setuid/setgid, en cuyo caso se ignora.

    Yo he probado haciéndolo así en el shell pero no sabía que había un bit en el ejecutable que gestionase la utilización de esta variable. ¿ como se sabe si este bit está activo?

    – Las definidas en el propio binario.

    Entiendo que esta es la opción infalible mientras no busques ejecutar tus programas sobre otras máquinas

    – En el fichero /etc/ld.so.cache, que contiene una lista compilada de bibliotecas candidatas encontradas previamente en la ruta de bibliotecas ampliada.

    Esta opción me parece la más adecuada ya que modificando este fichero podría cambiar de plataforma tan solo cargando este fichero y copiando las librerías

    – En la ruta predeterminada /lib, y despues en /usr/lib/. Si el binario fue enlazado con la opción -znodeflib, se omite este paso.

    ¿ Se pueden poner las librerías en este directorio?

    Gracias de nuevo:

    Kintxo

    • AsierPH 16 agosto, 2015 at 10:45 am -  Responder

      Buenas Kintxo, puedes hacerlo de cualquiera de las maneras, pero creo que la más segura es añadiendo tus librerías a /usr/lib y despues ejecutar ldconfig para que queden accesibles y a la hora de compilar tu programa, estas sean detectadas. Si tienes las librerías en un path que quieres mantener, añade este path en el fichero /etc/ld.so.conf y ejecuta ldconfig, también es una opción muy valida.
      No se si buscas algo más especifico, el proceso que has detallado es el que sigue ld.so para buscar las librerías necesarias.
      ¡Un saludo Kintxo, y muchas gracias por el comentario! Si necesitas algo más no dudes en preguntar.

  4. Jordi 20 marzo, 2014 at 4:42 pm -  Responder

    Tu como minimo ya tienes el LPI eh??? estoy precisamente en el capitulo de las librerias compartidas (y no me entero de nada xDDDD).

    Saludos y seguid asi.

    • AsierPH 20 marzo, 2014 at 5:54 pm -  Responder

      Me alegro de que te guste Jordi!, sobre todo tienes que tener claro que una librería es casi lo mismo que un programa normal ( no tienen main ), partiendo de esto intenta profundizar en el funcionamiento del enlazador y sus características. Una vez que entiendas bien como funcionan estas cosas ya esta, luego es cuestión de cuanto quieras bajar de nivel ( me refiero al funcionamiento a nivel mas cercano a la maquina ) o si tu mismo estas interesado en crear librerías 🙂
      Saludos

Deja tu comentario

Tu correo no sera publicado. Los campos requeridos están marcados *