一尘不染

在架构上,共享库(SO)和动态链接库(DLL)有什么区别?

linux

标题中的问题很多:就操作系统级别的实现而言,共享库和dll有何不同?

我之所以这样问,是因为我最近阅读了有关扩展Python的页面,其中指出:

Unix和Windows使用完全不同的范例来运行时加载代码。在尝试构建可以动态加载的模块之前,请了解系统的工作方式。

在Unix中,共享对象(.so)文件包含程序要使用的代码,以及它希望在程序中找到的函数和数据的名称。将文件加入程序后,文件代码中对这些功能和数据的所有引用都会更改为指向程序中将功能和数据放置在内存中的实际位置。这基本上是链接操作。

在Windows中,动态链接库(.dll)文件没有悬挂引用。取而代之的是,对功能或数据的访问将通过查找表进行。因此,DLL代码不必在运行时固定即可引用程序的内存;相反,代码已经使用DLL的查找表,并且在运行时修改了查找表以指向函数和数据。

有人可以详细说明吗?具体来说,我不确定我是否理解共享对象的描述,其中包含对共享对象的期望引用。同样,DLL听起来对我来说几乎是相同的机制。

这是对发生的一切的完整解释吗?有更好的吗?实际上有什么区别吗?

我知道如何链接到DLL或共享对象以及一些用于编写DLL的机制(.def清单,dllexport /
dllimport),因此,我明确地不打算在这些领域中寻找方法。我对后台发生的事情很感兴趣。

(编辑:另一个明显的观点-我知道它们在不同的平台上工作,使用不同的文件类型(ELF和PE),与ABI不兼容,等等。)


阅读 1556

收藏
2020-06-07

共1个答案

一尘不染

Dll与.so或.dylib(MacOS)文件所使用的机制几乎相同,因此很难确切解释它们之间的区别。

核心区别在于每种文件类型默认情况下可见的内容。.so文件导出语言(gcc)级链接-这意味着(默认情况下)拉入.so时(默认情况下)所有“外部”的C&c
++符号都可用于链接。这也意味着,解析.so文件本质上是一个链接步骤,加载程序不关心符号来自哪个.so文件。它仅遵循.a文件遵循的常规链接步骤规则,以某种顺序搜索指定的.so文件。

另一方面,Dll文件是一种操作系统功能,与语言的链接步骤完全分开。MSVC使用.lib文件来链接静态库和动态库(每个dll文件都会生成一个用于链接的成对的.lib文件),因此,一旦生成该程序,就将其完全“链接”(从语言中心角度)。

但是,在链接阶段,会在代表Dll的库中解析符号,从而允许链接程序在PE文件中构建导入表,其中包含dll的显式列表以及每个dll中引用的入口点。在加载时,Windows不必执行“链接”来解析共享库中的符号:该步骤已经完成-
Windows加载器仅加载dll并直接连接函数。

2020-06-07