架构上,共享对象(SO)和dynamic链接库(DLL)之间有什么区别?

这个问题在标题中有很多:在操作系统级别的实现方面,共享对象和dll有什么不同?

我问这个的原因是因为我最近读了这个关于扩展Python的页面 ,里面写道:

Unix和Windows使用完全不同的范例来运行代码加载。 在尝试构build可以dynamic加载的模块之前,请注意系统的工作方式。

在Unix中,共享对象(.so)文件包含程序要使用的代码,以及它期望在程序中find的函数和数据的名称。 当文件join程序时,所有对这些函数和文件代码中的数据的引用都被改变,以指向函数和数据被放置在内存中的程序中的实际位置。 这基本上是一个链接操作。

在Windows中,dynamic链接库(.dll)文件没有悬挂引用。 相反,访问函数或数据通过查找表。 所以DLL代码不需要在运行时修复来引用程序的内存; 相反,代码已经使用DLL的查找表,并且查找表在运行时被修改以指向函数和数据。

任何人都可以详细说明吗? 具体而言,我不知道我理解的共享对象的描述,包含他们期望find的引用。 同样,一个DLL听起来和我的机制差不多。

这是一个完整的解释,是怎么回事? 有更好的吗? 其实有什么不同吗?

我知道如何链接到一个DLL或共享对象和一些机制(.def列表,dllexport / dllimport)用于编写DLL,所以我明确没有寻找如何在这些领域; 我对后台正在发生的事情更感兴趣。

(编辑:另一个明显的观点 – 我知道他们在不同的平台上工作,使用不同的文件types(ELF vs PE),ABI不兼容等)

Dll与.so或.dylib(MacOS)文件使用的机制基本相同,因此很难解释具体的区别。

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

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

然而,在链接阶段,符号在表示Dll的lib中解析,允许链接器在PE文件中构建导入表,其中包含dll的明确列表以及每个dll中引用的入口点。 在加载时,Windows不必执行“链接”来解析共享库中的符号:该步骤已经完成–windows加载器只是加载DLL并直接挂接功能。