DLL中包含什么?它如何工作?


86

我总是在我的C#代码中引用DLL,但我想澄清它们仍然是个谜。这是有关DLL问题的一种脑力激荡。

我知道DLL是一个动态链接的库,这意味着另一个程序可以在运行时访问该库以获取“功能”。但是,请考虑以下带有Web.dll和的ASP.NET项目Business.dllWeb.dll是前端功能,它引用Business.dll类型和方法)。

  1. 在什么时候Web.dll动态链接到Business.dll?您注意到在Windows HDD中使用Word(等)时看似很小的任务经常会发生混乱,而我认为Word正在关闭并动态链接其他DLL的功能吗?

    1a。另外,什么加载和链接DLL-OS或某些运行时框架(如.NET框架)?

    1b。“链接”的过程是什么?是否进行兼容性检查?加载到同一内存中?链接实际上是什么意思?

  2. 什么实际执行DLL中的代码?它是否由处理器执行,或者在处理器理解DLL中的代码之前还有其他翻译或编译阶段?

    2a。对于使用C#.NET内置的DLL,正在运行什么:.NET框架或直接操作系统?

  3. Linux中的DLL是否可以在Windows系统上运行(如果存在),或者它们特定于操作系统?

  4. DLL是否特定于特定框架?使用C#.NET构建的DLL是否可以被使用Borland C ++构建的DLL使用?

    4a。如果对4的回答为“否”,那么DLL的意义是什么?为什么各种框架不使用自己的链接文件格式?例如:.NET内置的.exe知道.abc文件类型可以链接到其代码中。

  5. 让我们再回到Web.dll/Business.dll例子-让客户的类类型,我需要参考Business.dllWeb.dll。这必须意味着Business.dll包含某种有关客户类别实际的规范。如果我编译了我的Business.dll文件Delphi,例如:C#会理解它并能够创建客户类,或者是否存在某种标头信息或显示“嘿,抱歉,您只能从另一个Delphi DLL使用我” ?

    5a。方法同样适用;如何CreateInvoice()在DLL中编写方法,在C ++中进行编译,然后从C#访问并运行它?是什么阻止或允许我这样做?

  6. 关于DLL劫持,替换的(坏的)DLL当然必须包含与被劫持的DLL完全相同的方法签名和类型。我想,如果您能找到原始DLL中可用的方法,这将不难。

    6a。我的C#程序在决定是否可以访问另一个DLL?如果我被劫持的DLL包含与原始DLL完全相同的方法和类型,但它是用另一种语言编译的,那么它将起作用吗?

什么是DLL导入和DLL注册?


21
这个问题可能是要求SO历史上最长的答案。
Matti Virkkunen's

4
它应该是12个独立的问题。
Henk Holterman'9

2
这是一个很棒的问题,但我真的同意@Chaos和@Matti。这个问题需要更多关注,可以/应该分为多个不同的问题。
克里斯·汤普森

3
当我写它时我有点
不知所措

1
现在应该是社区Wiki。
leppie

Answers:


74

首先,您需要了解两种非常不同的DLL之间的区别。微软决定使用相同的文件扩展名与两个.NET(托管代码)和本地代码(.exe和.dll),但托管代码DLL和本机DLL是非常不同的内部。

1)在什么时候web.dll动态链接到business.dll?您注意到在Windows HDD中使用Word等时似乎看似很小的任务时会发生很多变化,我认为此Word即将关闭并动态链接其他DLL的功能吗?

1)对于.NET,通常是在执行第一个尝试从DLL中访问任何内容的方法时,按需加载DLL。这就是为什么如果无法加载DLL则可以在代码中的任何地方获取TypeNotFoundExceptions的原因。当类似Word的东西突然开始大量访问HDD时,很可能会交换(获取已交换到磁盘的数据以在RAM中腾出空间)

1a)另外,什么加载和链接DLL-O / S或某些运行时框架(例如.Net框架)?

1a)对于托管DLL,将加载.NET框架,然后进行JIT编译(将.NET字节码编译为本机代码)并链接DLL。对于本机DLL,它是操作系统的一个组件,可加载并链接DLL(无需编译,因为本机DLL已经包含本机代码)。

1b)“链接”的过程是什么?是否进行了兼容性检查?加载到同一内存中?链接实际上是什么意思?

1b)链接是指将调用代码中对DLL中符号(例如方法)的引用(例如方法调用)替换为DLL中事物的实际地址。这是必需的,因为在将DLL中的事物的最终地址加载到内存之前,无法知道它们的最终地址。

2)什么实际上执行DLL中的代码?它是否由处理器执行,或者在处理器理解DLL中的代码之前还有其他翻译或编译阶段?

2)在Windows上,.exe文件和.dll文件完全相同。本机.exe和.dll文件包含本机代码(与处理器执行的内容相同),因此无需进行翻译。托管的.exe和.dll文件包含.NET字节码,该字节码是首先JIT编译的(转换为本机代码)。

2a)对于从C#.net构建的DLL,正在运行什么?.Net框架还是直接操作系统?

2a)在对代码进行JIT编译后,其运行方式与任何代码完全相同。

3)说Linux的DLL是否可以在Windows系统上运行(如果存在),或者它们特定于操作系统?

3)只要两个平台上的框架都是最新的,并且无论谁编写DLL,都不会通过使用本机调用故意破坏兼容性,托管DLL可能会按原样工作。本机DLL无法使用,因为它们的格式是不同的(即使内部的机器代码是相同的,即使它们都用于同一处理器平台)也是如此。顺便说一句,在Linux上,“ DLL”被称为.so(共享库)文件。

4)它们特定于特定框架吗?使用C#.Net构建的DLL是否可以被使用Borland C ++构建的DLL使用(仅示例)?

4)托管DLL特定于.NET框架,但是自然地,它们可以与任何兼容的语言一起使用。只要每个人都使用相同的约定(调用约定(在计算机代码级别传递函数参数的方式),符号命名等),本机DLL就兼容。

5)回到web.dll / business.dll示例。为了获得客户的类类型,我需要从web.dll中引用business.dll。这必须意味着business.dll包含某种有关客户类实际上是什么的规范。如果我说过要编译我的business.dll文件,Delphi会C#理解它并能够创建客户类-或是否存在某种标题信息或显示“嘿,对不起,您只能从另一个delphi dll中使用我” 。

5)托管DLL包含它们包含的每个类,方法,字段等的完整描述。AFAIK Delphi不支持.NET,因此它将创建本机DLL,无法直接在.NET中使用。您可能可以使用PInvoke调用函数,但找不到类定义。我不使用Delphi,所以我不知道它如何使用DLL存储类型信息。例如,C ++依赖于包含类型声明且必须与DLL一起分发的头文件(.h)。

6)关于DLL劫持,一定要替换(坏)的DLL必须包含确切的方法签名,类型与被劫持的类型相同。我想,如果您能找到原始DLL中可用的方法等,就不会很难做到。

6)确实,如果可以轻松切换DLL,这并不难。可以使用代码签名来避免这种情况。为了使某人替换已签名的DLL,他们必须知道签名密钥,该密钥是保密的。

6a)这里有一个重复的问题,但这可以追溯到我的C#程序在决定是否可以访问另一个DLL?如果被劫持的DLL包含与原始DLL完全相同的方法和类型,但使用另一种语言进行编译,它将起作用吗?

6a)只要是使用任何.NET语言制作的托管DLL,它都可以工作。

  • 什么是DLL导入?和DLL注册?

“ DLL导入”可能意味着很多事情,通常意味着引用DLL文件并在其中使用东西。

DLL注册是在Windows上完成的操作,用于将DLL文件全局注册为COM组件,以使它们可用于系统上的任何软件。


3
我将在#4中添加.NET可以转换DLL,以便它们与理解/使用COM(通用对象模型)的任何本机程序兼容。很好的答案。
MerickOWA

7

.dll文件包含您可以在应用程序中使用的编译代码。

有时,用于编译.dll的工具很重要,有时则无关紧要。如果您可以在项目中引用.dll,则使用哪种工具对.dll的公开函数进行编码都没关系。

链接在运行时发生,这与静态链接库(例如您的类)不同,后者在编译时链接。

您可以将.dll视为一个黑盒子,它提供了应用程序所需的某些内容,而您不想自己编写。是的,了解.dll签名的人可能会在其中创建另一个带有不同代码的.dll文件,而您的调用应用程序不知道它们之间的区别。

高温超导


6

1)在什么时候web.dll动态链接到business.dll?您注意到在Windows HDD中使用Word等时似乎看似很小的任务时会发生很多变化,我认为此Word即将关闭并动态链接其他DLL的功能吗?

1)我认为您将链接与加载混淆了。链接是在对所有检查和余额进行测试以确保所要求的内容可用时的链接。在加载时,部分dll被加载到内存中或换出到页面文件中。这是您看到的高清活动。

动态链接与静态链接的不同之处在于,在静态链接中,所有目标代码在链接时都放入主.exe中。通过动态链接,目标代码被放入一个单独的文件(dll)中,并在与.exe不同的时间加载。

动态链接可以是隐式的(即应用程序与导入库链接),也可以是显式的(即应用程序使用LoadLibrary(ex)加载dll)。

在隐式情况下,/ DELAYLOAD可用于推迟dll的加载,直到应用程序实际需要它为止。否则,将其至少某些部分作为进程初始化的一部分加载(映射到进程地址空间中)。该dll还可以请求在进程处于活动状态时永远不要卸载它。

COM使用LoadLibrary加载COM dll。请注意,即使在隐式情况下,系统也使用类似于LoadLibrary的方法在进程启动时或首次使用时加载dll。

2)什么实际上执行DLL中的代码?它是否由处理器执行,或者在处理器理解DLL中的代码之前还有其他翻译或编译阶段?

2)dll包含目标代码,就像.exes一样。dll文件的格式几乎与exe文件的格式相同。我听说两个文件的标头只有一点不同。

对于从C#.net构建的DLL,.Net框架正在运行它。

3)说Linux的DLL是否可以在Windows系统上运行(如果存在),或者它们特定于操作系统?

3)DLL是特定于平台的。

4)它们特定于特定框架吗?使用C#.Net构建的DLL是否可以被使用Borland C ++构建的DLL使用(仅示例)?

4)如果特别注意或编写了一些附加的粘合代码,Dll可以与其他框架进行互操作。

当公司销售具有重叠功能的多种产品时,Dll非常有用。例如,我维护公司的30多种不同产品使用的栅格I / O DLL。如果您安装了多个产品,则dll的一次升级可以将所有产品升级为新的栅格格式。

5)回到web.dll / business.dll示例。为了获得客户的类类型,我需要从web.dll中引用business.dll。这必须意味着business.dll包含某种有关客户类实际上是什么的规范。如果我说过要编译我的business.dll文件,Delphi会C#理解它并能够创建客户类-或是否存在某种标题信息或显示“嘿,对不起,您只能从另一个delphi dll中使用我” 。

5)根据平台的不同,dll的功能可以通过.h文件,.tlb文件或.net上的其他方式以多种方式呈现。

6)关于DLL劫持,一定要替换(坏)的DLL必须包含确切的方法签名,类型与被劫持的类型相同。我想,如果您能找到原始DLL中可用的方法等,就不会很难做到。

6)dumpbin / exports和dumbin / imports是在.exe和.dlls上使用的有趣工具


3)DLL是特定
Henk Holterman 2010年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.