En informática , un enlazador dinámico es la parte de un sistema operativo que carga y enlaza las bibliotecas compartidas que necesita un ejecutable cuando se ejecuta (en " tiempo de ejecución "), copiando el contenido de las bibliotecas desde el almacenamiento persistente a la RAM , llenando tablas de salto y reubicando punteros . El sistema operativo específico y el formato del ejecutable determinan cómo funciona el enlazador dinámico y cómo se implementa.
El enlazado se suele denominar un proceso que se lleva a cabo cuando se compila el ejecutable , mientras que un enlazador dinámico es una parte especial de un sistema operativo que carga bibliotecas compartidas externas en un proceso en ejecución y luego vincula esas bibliotecas compartidas de manera dinámica al proceso en ejecución. Este enfoque también se denomina enlazado dinámico o enlazado tardío .
La biblioteca de vínculos dinámicos , o DLL, es la implementación de Microsoft del concepto de biblioteca compartida en los sistemas operativos Microsoft Windows y OS/2 . Estas bibliotecas suelen tener la extensión de archivo , (para bibliotecas que contienen controles ActiveX ) o (para controladores de sistemas heredados ). Los formatos de archivo para las DLL son los mismos que para los archivos EXE de Windows , es decir, Portable Executable (PE) para Windows de 32 y 64 bits , y New Executable (NE) para Windows de 16 bits . Al igual que con los EXE, las DLL pueden contener código , datos y recursos , en cualquier combinación. DLL
OCX
DRV
Los archivos de datos con el mismo formato de archivo que una DLL, pero con diferentes extensiones de archivo y posiblemente conteniendo solo secciones de recursos, pueden llamarse DLL de recursos. Ejemplos de dichas DLL incluyen bibliotecas de interfaz de usuario multilingües con extensión MUI
, bibliotecas de iconos , que a veces tienen la extensión ICL
, y archivos de fuentesFON
, que tienen las extensiones y FOT
. [1]
En la mayoría de los sistemas tipo Unix , la mayor parte del código de máquina que compone el enlazador dinámico es en realidad un ejecutable externo que el núcleo del sistema operativo carga y ejecuta primero en un espacio de direcciones de proceso recién construido como resultado de una llamada exec
a posix_spawn
funciones. En el momento del enlace, la ruta del enlazador dinámico que se debe utilizar se incorpora a la imagen del ejecutable.
Cuando se carga un archivo ejecutable, el núcleo del sistema operativo lee la ruta del enlazador dinámico y luego intenta cargar y ejecutar este otro binario ejecutable; si ese intento falla porque, por ejemplo, no hay ningún archivo con esa ruta, el intento de ejecutar el ejecutable original falla. A continuación, el enlazador dinámico carga la imagen ejecutable inicial y todas las bibliotecas enlazadas dinámicamente de las que depende e inicia el ejecutable. Como resultado, la ruta del enlazador dinámico es parte de la interfaz binaria de la aplicación del sistema operativo .
En sistemas tipo Unix que utilizan ELF para imágenes ejecutables y bibliotecas dinámicas, como Solaris , versiones de 64 bits de HP-UX , Linux , FreeBSD , NetBSD , OpenBSD y DragonFly BSD , la ruta del enlazador dinámico que se debe utilizar se incorpora en el momento del enlace en la .interp
sección del PT_INTERP
segmento del ejecutable. En esos sistemas, las bibliotecas compartidas cargadas dinámicamente se pueden identificar por el sufijo del nombre de archivo .so
(objeto compartido).
El enlazador dinámico puede ser influenciado para modificar su comportamiento durante la ejecución del programa o el enlace del programa, y los ejemplos de esto se pueden ver en las páginas del manual del enlazador en tiempo de ejecución para varios sistemas similares a Unix. [2] [3] [4] [5] [6] Una modificación típica de este comportamiento es el uso de variables de entornoLD_LIBRARY_PATH
y , que ajustan el proceso de enlace en tiempo de ejecución buscando bibliotecas compartidas en ubicaciones alternativas y cargando y enlazando a la fuerza bibliotecas que de otra manera no lo estarían, respectivamente. Un ejemplo es zlibc, [7] también conocido como , [a] que facilita la descompresión transparente cuando se usa a través del truco ; en consecuencia, es posible leer datos de archivos precomprimidos (gzip) en sistemas BSD y Linux como si los archivos no estuvieran comprimidos, lo que esencialmente permite a un usuario agregar compresión transparente al sistema de archivos subyacente, aunque con algunas salvedades. El mecanismo es flexible, lo que permite una adaptación trivial del mismo código para realizar un procesamiento adicional o alternativo de datos durante la lectura del archivo, antes de la provisión de dichos datos al proceso del usuario que lo ha solicitado. [8] [9]LD_PRELOAD
uncompress.so
LD_PRELOAD
En el sistema operativo Apple Darwin y en los sistemas operativos macOS e iOS basados en él, la ruta del enlazador dinámico que se debe utilizar se incorpora en el momento del enlace en uno de los comandos de carga de Mach-O en la imagen ejecutable. En esos sistemas, las bibliotecas compartidas cargadas dinámicamente se pueden identificar por el sufijo del nombre de archivo .dylib
o por su ubicación dentro del paquete de un marco.
El enlazador dinámico no solo enlaza el ejecutable de destino a las bibliotecas compartidas, sino que también coloca funciones de código de máquina en puntos de dirección específicos en la memoria que el ejecutable de destino conoce en el momento del enlace. Cuando un ejecutable desea interactuar con el enlazador dinámico, simplemente ejecuta la llamada específica de la máquina o la instrucción de salto a uno de esos puntos de dirección bien conocidos. Los ejecutables en las plataformas macOS e iOS a menudo interactúan con el enlazador dinámico durante la ejecución del proceso; incluso se sabe que un ejecutable puede interactuar con el enlazador dinámico, lo que hace que cargue más bibliotecas y resuelva más símbolos, horas después de su lanzamiento inicial. La razón por la que un programa macOS o iOS interactúa con el enlazador dinámico tan a menudo se debe tanto a las API Cocoa y Cocoa Touch de Apple como a Objective-C , el lenguaje en el que están implementados (consulte sus artículos principales para obtener más información).
El enlazador dinámico puede ser obligado a modificar parte de su comportamiento; sin embargo, a diferencia de otros sistemas operativos tipo Unix, estas modificaciones son sugerencias que pueden ser (y a veces son) ignoradas por el enlazador dinámico. Se pueden ver ejemplos de esto en dyld
la página del manual de . [10] Una modificación típica de este comportamiento es el uso de las variables de entorno DYLD_FRAMEWORK_PATH
y DYLD_PRINT_LIBRARIES
. La primera de las variables mencionadas anteriormente ajusta la ruta de búsqueda de los ejecutables para las bibliotecas compartidas, mientras que la última muestra los nombres de las bibliotecas a medida que se cargan y vinculan.
El enlazador dinámico macOS de Apple es un proyecto de código abierto publicado como parte de Darwin y se puede encontrar en el proyecto de código abierto de Apple dyld
. [11]
En sistemas operativos tipo Unix que utilizan XCOFF , como AIX , las bibliotecas compartidas cargadas dinámicamente usan el sufijo de nombre de archivo .a
.
Se puede influir en el enlazador dinámico para que modifique su comportamiento durante la ejecución del programa o durante el enlace del programa. Una modificación típica de este comportamiento es el uso de la LIBPATH
variable de entorno . Esta variable ajusta el proceso de enlace en tiempo de ejecución buscando bibliotecas compartidas en ubicaciones alternativas y cargando y vinculando a la fuerza bibliotecas que de otro modo no estarían disponibles, respectivamente.
El enlace dinámico de programas en lenguaje ensamblador en IBM OS/360 y sus sucesores se realiza normalmente mediante una macroinstrucción LINK que contiene una instrucción de llamada de supervisor que activa las rutinas del sistema operativo que hacen que el módulo de biblioteca que se va a vincular esté disponible para el programa. Los módulos de biblioteca pueden residir en una "STEPLIB" o "JOBLIB" especificada en las tarjetas de control y que sólo está disponible para una ejecución específica del programa, en una biblioteca incluida en la LINKLIST de la PARMLIB (especificada en el momento de inicio del sistema) o en el "área de paquetes de enlaces" donde se cargan módulos reentrantes específicos en el momento de inicio del sistema.
En el sistema operativo Multics , todos los archivos, incluidos los ejecutables, son segmentos . Una llamada a una rutina que no forma parte del segmento actual hará que el sistema encuentre el segmento al que se hace referencia, en la memoria o en el disco, y lo agregue al espacio de direcciones del proceso en ejecución. La vinculación dinámica es el método de operación normal y la vinculación estática (mediante el enlazador ) es la excepción.
El enlace dinámico es generalmente más lento (requiere más ciclos de CPU) que el enlace durante el tiempo de compilación, [12] como es el caso de la mayoría de los procesos ejecutados en tiempo de ejecución. Sin embargo, el enlace dinámico es a menudo más eficiente en términos de espacio (en disco y en memoria en tiempo de ejecución). Cuando una biblioteca está enlazada estáticamente, cada proceso que se ejecuta está enlazado con su propia copia de las funciones de la biblioteca que se están llamando. Por lo tanto, si una biblioteca es llamada muchas veces por diferentes programas, las mismas funciones en esa biblioteca se duplican en varios lugares en la memoria del sistema. El uso de bibliotecas compartidas y dinámicas significa que, en lugar de enlazar cada archivo a su propia copia de una biblioteca en el momento de la compilación y potencialmente desperdiciar espacio de memoria, solo se almacena una copia de la biblioteca en la memoria a la vez, liberando espacio de memoria para ser utilizado en otro lugar. [13] Además, en el enlace dinámico, una biblioteca solo se carga si realmente se está utilizando. [14]