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

时间:2021-06-12 13:25:06

The question is pretty much in the title: in terms of OS-level implementation, how are shared objects and dlls different?

问题在标题中:在操作系统级实现方面,共享对象和dll有何不同?

The reason I ask this is because I recently read this page on extending Python, which states:

我问这个问题的原因是因为我最近读了关于扩展Python的这一页,其中写道:

Unix and Windows use completely different paradigms for run-time loading of code. Before you try to build a module that can be dynamically loaded, be aware of how your system works.

Unix和Windows在运行时加载代码时使用完全不同的范例。在尝试构建可以动态加载的模块之前,请注意系统是如何工作的。

In Unix, a shared object (.so) file contains code to be used by the program, and also the names of functions and data that it expects to find in the program. When the file is joined to the program, all references to those functions and data in the file’s code are changed to point to the actual locations in the program where the functions and data are placed in memory. This is basically a link operation.

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

In Windows, a dynamic-link library (.dll) file has no dangling references. Instead, an access to functions or data goes through a lookup table. So the DLL code does not have to be fixed up at runtime to refer to the program’s memory; instead, the code already uses the DLL’s lookup table, and the lookup table is modified at runtime to point to the functions and data.

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

Could anyone elaborate on that? Specifically I'm not sure I understand the description of shared objects containing references to what they expect to find. Similarly, a DLL sounds like pretty much the same mechanism to me.

有人能详细解释一下吗?具体地说,我不确定我是否理解共享对象的描述,其中包含对它们期望找到的内容的引用。同样,DLL对我来说几乎是相同的机制。

Is this a complete explanation of what is going on? Are there better ones? Is there in fact any difference?

这是对正在发生的事情的一个完整的解释吗?有更好的吗?有什么区别吗?

I am aware of how to link to a DLL or shared object and a couple of mechanisms (.def listings, dllexport/dllimport) for writing DLLs so I'm explicitly not looking for a how to on those areas; I'm more intrigued as to what is going on in the background.

我知道如何链接到DLL或共享对象,以及一些机制(.def清单,dllexport/dllimport)用于编写DLL,因此我没有明确地寻找如何在这些区域中进行链接;我对幕后发生的事情更感兴趣。

(Edit: another obvious point - I'm aware they work on different platforms, use different file types (ELF vs PE), are ABI-incompatible etc...)

(编辑:另一个明显的观点——我知道他们在不同的平台上工作,使用不同的文件类型(ELF vs PE),以及abi不兼容等)。

1 个解决方案

#1


16  

A Dll is pretty much the same mechanism as used by .so or .dylib (MacOS) files, so it is very hard to explain exactly what the differences are.

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

The core difference is in what is visible by default from each type of file. .so files export the language (gcc) level linkage - which means that (by default) all C & c++ symbols that are "extern" are available for linking when .so's are pulled in. It also means that, as resolving .so files is essentially a link step, the loader doesn't care which .so file a symbol comes from. It just searches the specified .so files in some order following the usual link step rules that .a files adhere to.

核心区别在于,在默认情况下,每一种类型的文件中都可以看到哪些内容。因此,文件导出了语言(gcc)级链接——这意味着(默认情况下)所有的C和c++符号都是“extern”,当。这也意味着,在解析。so文件时,它本质上是一个链接步骤,加载程序并不关心哪个。它只是按照通常的链接步骤规则按一定顺序搜索指定的.so文件。

Dll files on the other hand are an Operating system feature, completely separate to the link step of the language. MSVC uses .lib files for linking both static, and dynamic libraries (each dll file generates a paired .lib file that is used for linking) so the resulting program is fully "linked" (from a language centric point of view) once its built.

另一方面,Dll文件是一个操作系统特性,完全独立于语言的链接步骤。MSVC使用.lib文件来链接静态库和动态库(每个dll文件生成一对用于链接的.lib文件),因此生成的程序在构建完成后会被完全“链接”(从以语言为中心的角度来看)。

During the link stage however, symbols were resolved in the lib's that represents the Dlls, allowing the linker to build the import table in the PE file containing an explicit list of dlls and the entry points referenced in each dll. At load time, Windows does not have to perform a "link" to resolving symbols from shared libraries: That step was already done - the windows loader just loads up the dll's and hooks up the functions directly.

然而,在链接阶段,符号在lib中被解析为表示dll的符号,允许链接器在PE文件中构建导入表,其中包含一个明确的dll列表和每个dll中引用的入口点。在加载时,Windows不必执行从共享库解析符号的“链接”:这一步已经完成——Windows加载程序只是加载dll并直接连接函数。

#1


16  

A Dll is pretty much the same mechanism as used by .so or .dylib (MacOS) files, so it is very hard to explain exactly what the differences are.

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

The core difference is in what is visible by default from each type of file. .so files export the language (gcc) level linkage - which means that (by default) all C & c++ symbols that are "extern" are available for linking when .so's are pulled in. It also means that, as resolving .so files is essentially a link step, the loader doesn't care which .so file a symbol comes from. It just searches the specified .so files in some order following the usual link step rules that .a files adhere to.

核心区别在于,在默认情况下,每一种类型的文件中都可以看到哪些内容。因此,文件导出了语言(gcc)级链接——这意味着(默认情况下)所有的C和c++符号都是“extern”,当。这也意味着,在解析。so文件时,它本质上是一个链接步骤,加载程序并不关心哪个。它只是按照通常的链接步骤规则按一定顺序搜索指定的.so文件。

Dll files on the other hand are an Operating system feature, completely separate to the link step of the language. MSVC uses .lib files for linking both static, and dynamic libraries (each dll file generates a paired .lib file that is used for linking) so the resulting program is fully "linked" (from a language centric point of view) once its built.

另一方面,Dll文件是一个操作系统特性,完全独立于语言的链接步骤。MSVC使用.lib文件来链接静态库和动态库(每个dll文件生成一对用于链接的.lib文件),因此生成的程序在构建完成后会被完全“链接”(从以语言为中心的角度来看)。

During the link stage however, symbols were resolved in the lib's that represents the Dlls, allowing the linker to build the import table in the PE file containing an explicit list of dlls and the entry points referenced in each dll. At load time, Windows does not have to perform a "link" to resolving symbols from shared libraries: That step was already done - the windows loader just loads up the dll's and hooks up the functions directly.

然而,在链接阶段,符号在lib中被解析为表示dll的符号,允许链接器在PE文件中构建导入表,其中包含一个明确的dll列表和每个dll中引用的入口点。在加载时,Windows不必执行从共享库解析符号的“链接”:这一步已经完成——Windows加载程序只是加载dll并直接连接函数。