问题在于标题:在操作系统级别的实现方面,共享对象和dll有何不同?
我之所以这样问是因为我最近阅读了this page关于扩展Python的内容,其中指出:
Unix和Windows使用完全不同的范例来运行时加载代码。在尝试构建可动态加载的模块之前,请注意系统的工作方式。
在Unix中,共享对象(.so)文件包含程序要使用的代码,以及它希望在程序中找到的函数和数据的名称。当文件加入程序时,文件代码中对这些函数和数据的所有引用都将更改为指向程序中将函数和数据放入内存的实际位置。这基本上是一个链接操作。
在Windows中,动态链接库(.dll)文件没有悬空引用。相反,对函数或数据的访问通过查找表进行。因此,DLL代码不必在运行时修复以引用程序的内存;相反,代码已经使用了DLL的查找表,并且在运行时修改了查找表以指向函数和数据。
有人可以详细说明吗?具体来说,我不确定我是否理解包含对他们期望找到的内容的引用的共享对象的描述。同样,DLL对我来说听起来几乎是一样的机制。
这是对发生了什么的完整解释吗?还有更好的吗?实际上有什么不同吗?
我知道如何链接到DLL或共享对象以及用于编写DLL的几种机制(.def listing,dllexport / dllimport),因此我明确没有在这些区域上寻找如何处理;我对后台发生的事情更感兴趣。
(编辑:另一个明显的观点 - 我知道他们在不同的平台上工作,使用不同的文件类型(ELF与PE),ABI不兼容等...)
答案 0 :(得分:16)
Dll几乎与.so或.dylib(MacOS)文件使用的机制相同,因此很难准确解释其差异。
核心区别在于默认情况下每种类型的文件都可见。 .so文件导出语言(gcc)级别链接 - 这意味着(默认情况下)所有C&当引入.so时,“extern”的c ++符号可用于链接。 这也意味着,由于解析.so文件本质上是一个链接步骤,加载器不关心符号来自哪个.so文件。它只是按照.a文件所遵循的常用链接步骤规则按某种顺序搜索指定的.so文件。
另一方面,Dll文件是一个操作系统功能,完全独立于该语言的链接步骤。 MSVC使用.lib文件链接静态和动态库(每个dll文件生成一个用于链接的配对.lib文件),因此生成的程序完全“链接”(从语言中心的角度来看)一旦构建。
在链接阶段,符号在表示Dlls的lib中被解析,允许链接器在PE文件中构建导入表,该表包含dll的明确列表和每个dll中引用的入口点。在加载时,Windows不必执行“链接”来解析共享库中的符号:该步骤已经完成 - Windows加载器只是加载dll并直接挂接函数。