tagger tag puddletag para mp3tag mac kid3 editar easytag linux windows shared-libraries

tag - Bibliotecas compartidas: método Windows vs Linux



mp3tag ubuntu (3)

Tengo una pregunta rápida sobre las bibliotecas compartidas de Windows (DLL) frente a las bibliotecas compartidas de Linux (SO).

¿Por qué es que cuando crea una DLL de Windows requiere que el programa cliente también se enlace con una biblioteca estática (archivo .lib), pero las aplicaciones creadas en Linux no requieren ningún enlace con dicha biblioteca estática?

¿Tiene algo que ver con la reubicación de código y similares? Gracias.


¿Por qué es que cuando crea una DLL de Windows requiere que el programa cliente también se enlace con una biblioteca estática (archivo .lib), pero las aplicaciones creadas en Linux no requieren ningún enlace con dicha biblioteca estática?

Esta es una decisión histórica de diseño tomada por Microsoft para que el vinculador pueda agregar referencias a DLL en un ejecutable sin que una versión particular de la DLL esté presente en el momento del enlace. La razón de esto fue que siempre ha habido diferentes versiones de Windows, con diferentes versiones de DLL. También en ese momento, Microsoft estaba cooperando con IBM en OS / 2 y el plan era que los programas de Windows también podrían ejecutarse en OS / 2. Bueno, Microsoft decidió "apañar" OS / 2, al lanzar su propio sistema operativo de grado profesional, basado en el núcleo NT. Pero esto significaba que, para el desarrollo, quería que los desarrolladores pudieran vincularse con las DLL del sistema, sin tener disponibles todas las diferentes variantes de la DLL. En su lugar, se habría utilizado una "plantilla" de vinculación dinámica para crear tanto la DLL como los ejecutables (ambos están en formato PE), que son estos archivos .lib particulares, que no son bibliotecas en absoluto, sino simples tablas de símbolos y ordinales ( Este es un hecho poco conocido, pero los símbolos binarios de PE pueden cargarse no solo por un identificador de cadena, sino también por un número entero, el denominado ordinal).

Un efecto secundario de los ordinales es que permiten ocultar los símbolos legibles por humanos, de modo que usted podría hacer uso de la DLL solo si conocía la relación ordinal de función ← →.

En Unix, la tradición era "lo construyes en el sistema en el que lo vas a ejecutar" o "tienes todos los archivos de sistema de destino en su lugar" . Así que nunca hubo un incentivo para separar la información de la biblioteca y el enlace. Técnicamente lo mismo funcionaría para DLL, también. Los PE pueden exportar un símbolo y una tabla de reubicación, lo que hacen las DLL, y un vinculador podría tomar toda la información que requiere de eso, muy bien.

Si ocultara símbolos con objetos compartidos de Unix, normalmente lo haría utilizando una struct única con todos los punteros de función en ella, y solo exportando una instancia de constante global de esta estructura por su nombre, que contiene una gran cantidad de no explícitamente punteros con nombre. Sin embargo, podría hacer exactamente lo mismo con las DLL de Windows.

TL; DR: La razón de esto no es técnica, sino una decisión de marketing y distribución.


En Windows, el programa cliente no necesita vincularse con una biblioteca estática para acceder a las funciones en una DLL. La vinculación dinámica puede ocurrir completamente en el tiempo de ejecución sin que el programa cliente sea consciente de la existencia de la DLL en el momento en que se compiló.

Por ejemplo, si quisiera llamar a un nombre de función "foo" en una DLL llamada "bar.dll", podría escribir código como este:

HINSTANCE hinst = LoadLibrary("bar.dll"); FARPROC foo = GetProcAddress(hinst, "foo"); foo();

Y "foo" y "bar.dll" podrían haber sido fácilmente valores que solo se establecieron en el tiempo de ejecución, por ejemplo, a través de un archivo de configuración o alguna otra entrada del usuario.

El propósito de la biblioteca estática es automatizar este proceso de carga dinámica, mediante la creación de apéndices que parecen ser funciones normales en lo que respecta al programa cliente, pero están vinculados a la DLL en tiempo de ejecución. Normalmente, esta vinculación se produce en el momento en que se carga el proceso del cliente, pero también se pueden generar bibliotecas que se carguen y se vinculen a pedido, por lo que la DLL no se llevará a la memoria hasta que sea realmente necesaria. Es la biblioteca estática la que determina cuándo se produce el enlace.

En su mayor parte, un compilador puede generar estas bibliotecas de forma automática, por lo que técnicamente no son necesarias cuando solo se vinculan a funciones DLL. Sin embargo, la única excepción a esto (que yo sepa) es cuando se vincula a variables compartidas.

En una DLL de Windows puede crear un segmento de datos compartidos con variables a las que se puede acceder mediante cualquier proceso que haya cargado esa DLL. La información sobre el tamaño y los tipos de esas variables se almacena en la biblioteca estática asociada, y no se puede determinar solo a partir de la DLL. Para acceder a esas variables, el programa cliente debe vincularse con la biblioteca estática para esa DLL.

Que yo sepa, las bibliotecas compartidas de Linux no admiten este concepto.

Actualizar

También debo mencionar que en Windows es posible crear una DLL donde los puntos de entrada de la función solo se exportan por ordinal (número) en lugar de nombre. Esto se puede considerar como una forma de ocultación de datos y normalmente se usará cuando un implementador quiera que ciertas funciones permanezcan privadas.

Alguien con acceso a la biblioteca estática podría llamar a esas funciones por su nombre, ya que la biblioteca tendría los detalles que vinculan el nombre de la función con el ordinal apropiado. Cualquier persona que solo tuviera la DLL tendría que enlazar manualmente a las funciones por ordinal o generar su propia biblioteca estática con nombres inventados.


No en realidad con la reubicación de código, eso es un problema totalmente diferente. Se trata de una diferencia en arquitectura:

  • En Windows, una DLL es como un ejecutable (EXE). La diferencia principal entre un EXE y una DLL es que el EXE tiene un punto de entrada (función principal / WinMain) y por lo tanto se puede usar para iniciar un proceso, mientras que las DLL solo se pueden cargar en un proceso preexistente. Pero ver (1)

  • En Linux, un .so funciona de manera similar a una biblioteca estática (.a). La principal diferencia es que el archivo .so se puede vincular con un programa en ejecución, mientras que el archivo .a solo se puede vincular al compilar el programa.

Una consecuencia de este enfoque es que en linux se puede usar el mismo archivo para compilar y ejecutar el programa. Pero en Windows necesita una biblioteca adecuada (LIB) para vincular el programa. En realidad, la biblioteca que corresponde a una DLL generalmente no tiene más que los nombres de las funciones, para satisfacer al vinculador y los apéndices para hacer la reubicación. Pero ver (2)

(1) Bueno, las DLL también tienen un punto de entrada, pero no se usa como función principal, solo como una especie de gancho de inicialización / finalización.

(2) Algunos enlazadores son lo suficientemente inteligentes como para poder, en algunos casos simples, vincularse a una DLL utilizando la DLL, sin la necesidad de un archivo LIB adicional. Creo que al menos el enlazador MinGW puede hacer eso.