Qu'y a-t-il dans une DLL et comment ça marche?

86

Je fais toujours référence aux DLL dans mon code C #, mais elles sont restées un peu un mystère que je voudrais clarifier. Il s'agit d'une sorte de mémoire de questions concernant les DLL.

Je comprends qu'une DLL est une bibliothèque liée dynamiquement, ce qui signifie qu'un autre programme peut accéder à cette bibliothèque au moment de l'exécution pour obtenir une «fonctionnalité». Cependant, considérez le projet ASP.NET suivant avec Web.dllet Business.dll( Web.dllest la fonctionnalité frontale et fait référence Business.dllaux types et méthodes).

  1. À quel point le Web.dlllien est-il dynamique Business.dll? Vous remarquez beaucoup de battements de disque dur Windows pour des tâches apparemment petites lors de l'utilisation de Word (etc.) et je pense que Word se déclenche et lie dynamiquement les fonctionnalités d'autres DLL?

    1a. En outre, qu'est-ce qui charge et lie la DLL - le système d'exploitation ou un cadre d'exécution tel que le framework .NET?

    1b. Quel est le processus de «liaison»? Des contrôles de compatibilité sont-ils effectués? Chargement dans la même mémoire? Que signifie réellement le lien?

  2. Qu'est-ce qui exécute réellement le code dans la DLL? Est-il exécuté par le processeur ou y a-t-il une autre étape de traduction ou de compilation avant que le processeur ne comprenne le code à l'intérieur de la DLL?

    2a. Dans le cas d'une DLL intégrée en C # .NET, qu'est-ce qui l'exécute: le framework .NET ou directement le système d'exploitation?

  3. Une DLL de Linux fonctionne-t-elle sur un système Windows (si une telle chose existe) ou est-elle spécifique au système d'exploitation?

  4. Les DLL sont-elles spécifiques à un framework particulier? Une DLL créée à l'aide de C # .NET peut-elle être utilisée par une DLL créée avec, par exemple, Borland C ++?

    4a. Si la réponse à 4 est «non», alors quel est l'intérêt d'une DLL? Pourquoi les différents frameworks n'utilisent-ils pas leurs propres formats pour les fichiers liés? Par exemple: un .exe intégré à .NET sait qu'un type de fichier .abc est quelque chose qu'il peut lier dans son code.

  5. Revenons à l' exemple Web.dll/ Business.dll- pour obtenir un type de classe de client à Business.dllpartir duquel je dois me référer Web.dll. Cela doit signifier qu'il Business.dllcontient une sorte de spécification de ce qu'est réellement une classe client. Si j'avais compilé mon Business.dllfichier dans, disons, Delphi: C # le comprendrait-il et serait-il capable de créer une classe client, ou y a-t-il une sorte d'informations d'en-tête ou quelque chose qui dit "hé désolé, vous ne pouvez m'utiliser qu'à partir d'une autre DLL Delphi" ?

    5a. Il en va de même pour les méthodes; puis-je écrire une CreateInvoice()méthode dans une DLL, la compiler en C ++, puis y accéder et l'exécuter à partir de C #? Qu'est-ce qui m'arrête ou me permet de faire ça?

  6. En ce qui concerne le détournement de DLL, la DLL de remplacement (mauvaise) doit sûrement contenir les signatures et les types de méthode exacts que celui qui est détourné. Je suppose que ce ne serait pas difficile à faire si vous pouviez découvrir les méthodes disponibles dans la DLL d'origine.

    6a. Qu'est-ce qui dans mon programme C # décide si je peux accéder à une autre DLL? Si ma DLL détournée contenait exactement les mêmes méthodes et types que l'original mais qu'elle était compilée dans une autre langue, cela fonctionnerait-il?

Qu'est-ce que l'importation de DLL et l'enregistrement de DLL?

Remotec
la source
21
Cette question pourrait bien demander la réponse la plus longue de l'histoire des SO.
Matti Virkkunen le
4
Cela aurait dû être 12 questions distinctes.
Henk Holterman le
2
C'est une question géniale, mais je suis vraiment d'accord avec @Chaos et @Matti. Cette question doit être plus ciblée et pourrait / devrait être divisée en un certain nombre de questions différentes.
Chris Thompson
3
C'était un peu une décharge de cerveau quand je l'ai écrit + je voulais centraliser les connaissances dans un domaine :)
Remotec
1
Devrait être un wiki communautaire maintenant.
leppie

Réponses:

74

Tout d'abord, vous devez comprendre la différence entre deux types très différents de DLL. Microsoft a décidé d'utiliser les mêmes extensions de fichier (.exe et .dll) avec .NET (code managé) et le code natif, mais les DLL de code managé et les DLL natives sont très différentes à l'intérieur.

1) À quel moment web.dll est-il lié dynamiquement à business.dll? Vous remarquez beaucoup de battements de disque dur Windows pour des tâches apparemment petites lors de l'utilisation de Word, etc. et je pense que ce mot se déclenche et lie dynamiquement les fonctionnalités d'autres DLL?

1) Dans le cas de .NET, les DLL sont généralement chargées à la demande lorsque la première méthode essayant d'accéder à quoi que ce soit à partir de la DLL est exécutée. C'est pourquoi vous pouvez obtenir TypeNotFoundExceptions n'importe où dans votre code si une DLL ne peut pas être chargée. Quand quelque chose comme Word commence soudainement à accéder beaucoup au disque dur, il est probable qu'il permute (obtenir des données qui ont été échangées sur le disque pour faire de la place dans la RAM)

1a) De plus, qu'est-ce qui charge et lie la DLL - l'O / S ou un cadre d'exécution tel que le framework .Net?

1a) Dans le cas des DLL gérées, le framework .NET est ce qui charge, JIT compile (compile le bytecode .NET en code natif) et lie les DLL. Dans le cas des DLL natives, c'est un composant du système d'exploitation qui charge et lie la DLL (aucune compilation n'est nécessaire car les DLL natives contiennent déjà du code natif).

1b) Quel est le processus de "liaison"? Des vérifications sont-elles effectuées pour vérifier la compatibilité? Chargement dans la même mémoire? Que signifie réellement le lien?

1b) La liaison se produit lorsque les références (par exemple les appels de méthode) dans le code appelant aux symboles (par exemple les méthodes) dans la DLL sont remplacées par les adresses réelles des éléments de la DLL. Cela est nécessaire car les adresses éventuelles des éléments de la DLL ne peuvent pas être connues avant son chargement en mémoire.

2) Qu'est-ce qui exécute réellement le code dans la DLL? Est-il exécuté par le processeur ou y a-t-il une autre étape de traduction ou de compilation avant que le processeur ne comprenne le code à l'intérieur de la DLL?

2) Sous Windows, les fichiers .exe et .dll sont assez identiques. Les fichiers .exe et .dll natifs contiennent du code natif (le même que le processeur exécute), il n'est donc pas nécessaire de traduire. Les fichiers .exe et .dll gérés contiennent du bytecode .NET qui est d'abord compilé par JIT (traduit en code natif).

2a) Dans le cas d'une DLL construite à partir de C # .net, qu'est-ce qui l'exécute? Le framework .Net ou le système d'exploitation directement?

2a) Une fois le code compilé JIT, il est exécuté exactement de la même manière que n'importe quel code.

3) Est-ce qu'une DLL de par exemple Linux fonctionne sur un système Windows (si une telle chose existe) ou est-elle spécifique au système d'exploitation?

3) Les DLL gérées peuvent fonctionner telles quelles, tant que les frameworks sur les deux plates-formes sont à jour et que celui qui a écrit la DLL n'a pas délibérément rompu la compatibilité en utilisant des appels natifs. Les DLL natives ne fonctionneront pas comme dans, car les formats sont différents (même si le code machine à l'intérieur est le même, s'ils sont tous les deux pour la même plate-forme de processeur). Par ailleurs, sous Linux, les «DLL» sont appelées fichiers .so (objets partagés).

4) Sont-ils spécifiques à un cadre particulier? Une DLL créée à l'aide de C # .Net peut-elle être utilisée par une DLL créée avec Borland C ++ (exemple uniquement)?

4) Les DLL gérées sont propres au framework .NET, mais elles fonctionnent naturellement avec n'importe quel langage compatible. Les DLL natives sont compatibles tant que tout le monde utilise les mêmes conventions (conventions d'appel (comment les arguments de fonction sont passés au niveau du code machine), dénomination des symboles, etc.)

5) Revenons à l'exemple web.dll / business.dll. Pour obtenir un type de classe de client, je dois référencer business.dll à partir de web.dll. Cela doit signifier que business.dll contient une spécification d'une sorte de ce qu'est réellement une classe client. Si j'avais compilé mon fichier business.dll dans, disons, Delphi le comprendrait et serait capable de créer une classe client - ou y a-t-il une sorte d'informations d'en-tête ou quelque chose qui dit "hé désolé, vous ne pouvez m'utiliser qu'à partir d'une autre dll delphi" .

5) Les DLL gérées contiennent une description complète de chaque classe, méthode, champ, etc. qu'elles contiennent. AFAIK Delphi ne prend pas en charge .NET, il créerait donc des DLL natives, qui ne peuvent pas être utilisées directement dans .NET. Vous pourrez probablement appeler des fonctions avec PInvoke, mais les définitions de classe ne seront pas trouvées. Je n'utilise pas Delphi donc je ne sais pas comment il stocke les informations de type avec les DLL. C ++, par exemple, repose sur des fichiers d'en-tête (.h) qui contiennent les déclarations de type et doivent être distribués avec la DLL.

6) En ce qui concerne le détournement de DLL, la DLL de remplacement (mauvaise) doit sûrement contenir les signatures de méthode exactes, types comme celui qui est détourné. Je suppose que ce ne serait pas difficile à faire si vous pouviez découvrir quelles méthodes, etc. étaient disponibles dans la DLL d'origine.

6) En effet, ce n'est pas difficile à faire si vous pouvez facilement changer de DLL. La signature de code peut être utilisée pour éviter cela. Pour que quelqu'un remplace une DLL signée, il doit connaître la clé de signature, qu'elle garde secrète.

6a) Une petite question répétée ici mais cela revient à ce qui dans mon programme C # décide si je peux accéder à une autre DLL? Si ma DLL détournée contenait exactement les mêmes méthodes et types que l'original mais qu'elle était compilée dans une autre langue, cela fonctionnerait-il?

6a) Cela fonctionnerait tant qu'il s'agit d'une DLL gérée, faite avec n'importe quel langage .NET.

  • Qu'est-ce que l'importation de DLL? et enregistrement dll?

«Importation de DLL» peut signifier beaucoup de choses, généralement cela signifie référencer un fichier DLL et utiliser des éléments qu'il contient.

L'enregistrement de DLL est quelque chose qui se fait sous Windows pour enregistrer globalement les fichiers DLL en tant que composants COM afin de les rendre disponibles à n'importe quel logiciel du système.

Matti Virkkunen
la source
3
J'ajouterais au n ° 4 que .NET peut traduire les DLL afin qu'elles soient compatibles avec tout programme natif qui comprend / utilise COM (Common Object Model). Très bonnes réponses tho.
MerickOWA le
7

Un fichier .dll contient du code compilé que vous pouvez utiliser dans votre application.

Parfois, l'outil utilisé pour compiler le fichier .dll est important, parfois non. Si vous pouvez référencer le .dll dans votre projet, peu importe quel outil a été utilisé pour coder les fonctions exposées du .dll.

La liaison se produit au moment de l'exécution, contrairement aux bibliothèques liées statiquement, telles que vos classes, qui se lient au moment de la compilation.

Vous pouvez considérer un fichier .dll comme une boîte noire qui fournit quelque chose dont votre application a besoin que vous ne voulez pas écrire vous-même. Oui, quelqu'un comprenant la signature du .dll pourrait créer un autre fichier .dll avec un code différent à l'intérieur et votre application appelante ne pourrait pas connaître la différence.

HTH

Beth
la source
6

1) À quel moment web.dll est-il lié dynamiquement à business.dll? Vous remarquez beaucoup de battements de disque dur Windows pour des tâches apparemment petites lors de l'utilisation de Word, etc. et je pense que ce mot se déclenche et lie dynamiquement les fonctionnalités d'autres DLL?

1) Je pense que vous confondez la liaison avec le chargement. Le lien est lorsque tous les freins et contrepoids sont testés pour s'assurer que ce qui est demandé est disponible. Au moment du chargement, des parties de la dll sont chargées en mémoire ou échangées vers le fichier d'échange. C'est l'activité HD que vous voyez.

La liaison dynamique est différente de la liaison statique en ce que dans la liaison statique, tout le code objet est placé dans le fichier .exe principal au moment de la liaison. Avec la liaison dynamique, le code objet est placé dans un fichier séparé (le dll) et il est chargé à un moment différent du .exe.

La liaison dynamique peut être implicite (c'est-à-dire que l'application est liée à une bibliothèque d'importation) ou explicite (c'est-à-dire que l'application utilise LoadLibrary (ex) pour charger la dll).

Dans le cas implicite, / DELAYLOAD peut être utilisé pour reporter le chargement de la dll jusqu'à ce que l'application en ait réellement besoin. Sinon, au moins certaines parties de celui-ci sont chargées (mappées dans l'espace d'adressage du processus) dans le cadre de l'initiation du processus. La dll peut également demander qu'elle ne soit jamais déchargée tant que le processus est actif.

COM utilise LoadLibrary pour charger les DLL COM. Notez que même dans le cas implicite, le système utilise quelque chose de similaire à LoadLibrary pour charger la dll au démarrage du processus ou lors de la première utilisation.

2) Qu'est-ce qui exécute réellement le code dans la DLL? Est-il exécuté par le processeur ou y a-t-il une autre étape de traduction ou de compilation avant que le processeur ne comprenne le code à l'intérieur de la DLL?

2) Les DLL contiennent du code objet comme .exes. Le format du fichier dll est presque identique au format d'un fichier exe. J'ai entendu dire qu'il n'y a qu'un seul élément différent dans les en-têtes des deux fichiers.

Dans le cas d'une DLL créée à partir de C # .net, le framework .Net l'exécute.

3) Est-ce qu'une DLL de par exemple Linux fonctionne sur un système Windows (si une telle chose existe) ou est-elle spécifique au système d'exploitation?

3) Les DLL sont spécifiques à la plate-forme.

4) Sont-ils spécifiques à un cadre particulier? Une DLL créée à l'aide de C # .Net peut-elle être utilisée par une DLL créée avec Borland C ++ (exemple uniquement)?

4) Les DLL peuvent interagir avec d'autres frameworks si des précautions particulières sont prises ou si du code glue supplémentaire est écrit.

Les DLL sont très utiles lorsqu'une entreprise vend plusieurs produits dont les capacités se chevauchent. Par exemple, je gère une dll d'E / S raster qui est utilisée par plus de 30 produits différents dans l'entreprise. Si vous avez plusieurs produits installés, une mise à niveau de la DLL peut mettre à niveau tous les produits vers de nouveaux formats raster.

5) Revenons à l'exemple web.dll / business.dll. Pour obtenir un type de classe de client, je dois référencer business.dll à partir de web.dll. Cela doit signifier que business.dll contient une spécification d'une sorte de ce qu'est réellement une classe client. Si j'avais compilé mon fichier business.dll dans, disons, Delphi le comprendrait et serait capable de créer une classe client - ou y a-t-il une sorte d'informations d'en-tête ou quelque chose qui dit "hé désolé, vous ne pouvez m'utiliser qu'à partir d'une autre dll delphi" .

5) Selon la plate-forme, les capacités d'une dll sont présentées de différentes manières, via des fichiers .h, des fichiers .tlb ou d'autres moyens sur .net.

6) En ce qui concerne le détournement de DLL, la DLL de remplacement (mauvaise) doit sûrement contenir les signatures de méthode exactes, types comme celui qui est détourné. Je suppose que ce ne serait pas difficile à faire si vous pouviez découvrir quelles méthodes, etc. étaient disponibles dans la DLL d'origine.

6) dumpbin / exports et dumbin / importations sont des outils intéressants à utiliser sur .exe et .dlls

edgman
la source
3) Les DLL sont spécifiques à la plate - forme
Henk Holterman