dado que las DLL son esencialmente las mismas que las EXEs, la elección de las cuales producir como parte del proceso de enlace es para mayor claridad, ya que es posible exportar funciones y datos desde cualquiera de ellas.
no es posible ejecutar directamente un DLL, ya que requiere un EXE para que el sistema operativo lo cargue a través de un punto de entrada, de ahí la existencia de utilidades como RUNDLL.EXE o RUNDLL32.EXE que proporcionan el punto de entrada y un marco mínimo para DLL que contienen suficiente funcionalidad para ejecutarse sin mucho soporte.,
Las DLL proporcionan un mecanismo para el código y los datos compartidos, lo que permite a un desarrollador de Código/datos compartidos actualizar la funcionalidad sin requerir que las aplicaciones se vuelvan a vincular o se vuelvan a compilar. Desde el punto de vista del desarrollo de Aplicaciones, Windows y OS/2 pueden considerarse como una colección de DLL que se actualizan, lo que permite que las aplicaciones para una versión del sistema operativo funcionen en una versión posterior, siempre que el proveedor del sistema operativo se haya asegurado de que las interfaces y la funcionalidad sean compatibles.,
Las DLL se ejecutan en el espacio de memoria del proceso de llamada y con los mismos permisos de acceso, lo que significa que hay poca sobrecarga en su uso, pero también que no hay protección para el EXE de llamada si la DLL tiene algún tipo de error.
gestión de Memoriaeditar
en la API de Windows, los archivos DLL están organizados en secciones. Cada sección tiene su propio conjunto de atributos, como ser de escritura o de solo lectura, ejecutable (para código) o no ejecutable (para datos), y así sucesivamente.,
el código en una DLL suele ser compartido entre todos los procesos que utilizan la DLL; es decir, ocupan un solo lugar en la memoria física, y no ocupan espacio en el archivo de página. Windows no usa código independiente de la posición para sus DLL; en su lugar, el código sufre reubicación a medida que se carga, fijando direcciones para todos sus puntos de entrada en ubicaciones que están libres en el espacio de memoria del primer proceso para cargar la DLL., En versiones anteriores de Windows, en las que todos los procesos en ejecución ocupaban un único espacio de direcciones común, una sola copia del código de la DLL siempre sería suficiente para todos los procesos. Sin embargo, en las versiones más recientes de Windows que utilizan espacios de direcciones separados para cada programa, solo es posible utilizar la misma copia reubicada de la DLL en varios programas si cada programa tiene las mismas direcciones virtuales libres para acomodar el código de la DLL., Si algunos programas (o su combinación de DLL ya cargados) no tienen esas direcciones libres, entonces se necesitará crear una copia física adicional del Código del DLL, usando un conjunto diferente de puntos de entrada reubicados. Si se desea recuperar la memoria física ocupada por una sección de Código, su contenido se descarta y luego se vuelve a cargar directamente desde el archivo DLL según sea necesario.
en contraste con las secciones de código, las secciones de datos de una DLL son generalmente privadas; es decir, cada proceso que usa la DLL tiene su propia copia de todos los datos de la DLL., Opcionalmente, las secciones de datos se pueden compartir, lo que permite la comunicación entre procesos a través de esta área de memoria compartida. Sin embargo, debido a que las restricciones de usuario no se aplican al uso de la memoria DLL compartida, esto crea un agujero de seguridad; es decir, un proceso puede dañar los datos compartidos, lo que probablemente causará que todos los demás procesos de intercambio se comporten de manera indeseable. Por ejemplo, un proceso que se ejecuta en una cuenta de invitado puede de esta manera corromper otro proceso que se ejecuta en una cuenta privilegiada. Esta es una razón importante para evitar el uso de secciones compartidas en DLL.,
si un DLL está comprimido por ciertos empaquetadores ejecutables (por ejemplo, UPX), todas sus secciones de código se marcan como lectura y escritura, y no se compartirán. Las secciones de código de lectura y escritura, al igual que las secciones de datos privados, son privadas para cada proceso. Por lo tanto, las DLL con secciones de datos compartidos no deben comprimirse si están destinadas a ser utilizadas simultáneamente por varios programas, ya que cada instancia de programa tendría que llevar su propia copia de la DLL, lo que resulta en un mayor consumo de memoria.
Import librariesEdit
Al igual que las bibliotecas estáticas, las bibliotecas de importación para DLL son notadas por el .,extensión de archivo lib. Por ejemplo, kernel32.dll, la biblioteca dinámica principal para las funciones base de Windows, como la creación de archivos y la administración de memoria, está vinculada a través de kernel32.lib. La forma habitual de distinguir una biblioteca de importación de una biblioteca estática adecuada es por tamaño: la biblioteca de importación es mucho más pequeña, ya que solo contiene símbolos que hacen referencia a la DLL real, para ser procesados en tiempo de enlace. Sin embargo, ambos son archivos en formato ar de Unix.
La vinculación a bibliotecas dinámicas generalmente se maneja mediante la vinculación a una biblioteca de importación al compilar o vincular para crear un archivo ejecutable., El ejecutable creado contiene una tabla de direcciones de importación (IAT) mediante la cual se hace referencia a todas las llamadas a funciones DLL (cada función DLL referenciada contiene su propia entrada en el IAT). En tiempo de ejecución, el IAT se llena con las direcciones apropiadas que apuntan directamente a una función en la DLL cargada por separado.
en Cygwin / MSYS y MinGW, las bibliotecas de importación reciben convencionalmente el sufijo .dll.a
, combinando el sufijo DLL de Windows y el sufijo ar de Unix., El formato de archivo es similar, pero los símbolos utilizados para marcar las importaciones son diferentes (_head_foo_dll vs_ _ IMPORT _ DESCRIPTOR _ foo). Aunque su cadena de herramientas GNU Binutils puede generar bibliotecas de importación y vincularlas, es más rápido vincularlas directamente a la DLL. Una herramienta experimental en MinGW llamada genlib se puede utilizar para generar libs de importación con símbolos de estilo MSVC.
Symbol resolution and bindingEdit
cada función exportada por una DLL se identifica mediante un ordinal numérico y, opcionalmente, un nombre. Del mismo modo, las funciones se pueden importar desde una DLL ya sea por ordinal o por nombre., El ordinal representa la posición del puntero de dirección de la función en la tabla de direcciones de exportación DLL. Es común que las funciones internas sean exportadas solo por ordinal. Para la mayoría de las funciones de la API de Windows, solo los nombres se conservan en diferentes versiones de Windows; los ordinales están sujetos a cambios. Por lo tanto, no se puede importar de forma fiable las funciones de la API de Windows por sus ordinales.
importar funciones por ordinal solo proporciona un rendimiento ligeramente mejor que importarlas por Nombre: las tablas de exportación de DLL están ordenadas por nombre, por lo que se puede usar una búsqueda binaria para encontrar una función., El índice del nombre encontrado se utiliza para buscar el ordinal en la tabla de exportación Ordinal. En ventanas de 16 bits, la tabla de nombres no estaba ordenada, por lo que la sobrecarga de búsqueda de nombres era mucho más notable.
también es posible enlazar un ejecutable a una versión específica de una DLL, es decir, resolver las direcciones de funciones importadas en tiempo de compilación. Para las importaciones enlazadas, el enlazador guarda la marca de tiempo y la suma de comprobación de la DLL a la que está enlazada la importación. En tiempo de ejecución, Windows comprueba si se está utilizando la misma versión de la biblioteca, y si es así, Windows omite el procesamiento de las importaciones., De lo contrario, si la biblioteca es diferente de la que estaba vinculada, Windows procesa las importaciones de una manera normal.
los ejecutables enlazados se cargan algo más rápido si se ejecutan en el mismo entorno para el que se compilaron, y exactamente al mismo tiempo si se ejecutan en un entorno diferente, por lo que no hay inconveniente para vincular las importaciones. Por ejemplo, todas las aplicaciones estándar de Windows están vinculadas a las DLL del sistema de su respectiva versión de Windows. Una buena oportunidad para vincular las importaciones de una aplicación a su entorno de destino es durante la instalación de la aplicación., Esto mantiene las bibliotecas ‘enlazadas’ hasta la próxima actualización del sistema operativo. Sin embargo, cambia la suma de comprobación del ejecutable, por lo que no es algo que se pueda hacer con programas firmados, o programas que son administrados por una herramienta de administración de configuración que usa sumas de comprobación (como sumas de comprobación MD5) para administrar versiones de archivos. A medida que las versiones más recientes de Windows han dejado de tener direcciones fijas para cada biblioteca cargada (por razones de seguridad), la oportunidad y el valor de vincular un ejecutable está disminuyendo.,
Explicit run-time linkingEdit
los archivos DLL pueden cargarse explícitamente en tiempo de ejecución, un proceso conocido simplemente como enlace Dinámico en tiempo de ejecución por Microsoft, mediante el uso de la función API LoadLibrary
(o LoadLibraryEx
). La función API GetProcAddress
se utiliza para buscar símbolos exportados por nombre, y FreeLibrary
– para descargar el DLL. Estas funciones son análogas a dlopen
, dlsym
y dlclose
en el estándar POSIX de la API.,
el procedimiento para la vinculación explícita en tiempo de ejecución es el mismo en cualquier lenguaje que soporte punteros a funciones, ya que depende de la API de Windows en lugar de construcciones de lenguaje.
carga Retrasadaeditar
normalmente, una aplicación que está vinculada a la biblioteca de importación de una DLL no se iniciará si la DLL no se puede encontrar, porque Windows no ejecutará la aplicación a menos que pueda encontrar todas las DLL que la aplicación pueda necesitar. Sin embargo, una aplicación puede estar vinculada a una biblioteca de importación para permitir la carga retardada de la biblioteca dinámica.,En este caso, el sistema operativo no intentará encontrar o cargar la DLL cuando se inicie la aplicación; en su lugar, el enlazador incluye un stub en la aplicación que intentará encontrar y cargar la DLL a través de LoadLibrary y GetProcAddress cuando se llame a una de sus funciones. Si la DLL no se puede encontrar o cargar, o la función llamada no existe, la aplicación generará una excepción, que puede ser capturada y manejada apropiadamente. Si la aplicación no maneja la excepción, será atrapada por el sistema operativo, que terminará el programa con un mensaje de error.,
el mecanismo de retardo de carga también proporciona ganchos de notificación, lo que permite a la aplicación Realizar un procesamiento adicional o manejo de errores cuando se carga la DLL y/o se llama a cualquier función DLL.
Deja una respuesta