在Linux中,可执行的ELF文件分别是什么
- 静态链接器
- 动态链接器
- 装载机
- 动态加载器?
其中哪些被调用
- 经过
execve()
- 经过
dlopen()
?
它们如何被execve()
or调用来解决or调用可执行文件dlopen()
的先有鸡还是先有蛋的问题?execve()
dlopen()
谢谢。
答案1
我认为你正在使用杰夫·达西的定义:
- 静态链接涉及在编译时解析符号,而动态链接涉及在运行时解析符号;
- 静态加载涉及在加载时映射可执行文件和库,而动态加载涉及在进程启动后映射库。
试图把所有东西都分开确实没有意义。相反,您应该考虑特征对:
- 静态加载、静态链接:链接器
/usr/bin/ld
通常与静态库 (.a
) 一起;加载器是内核; - 静态加载,动态链接:链接器
/usr/bin/ld
又是,但是带有共享库(.so
);加载器是二进制文件的解释器,例如/lib64/ld-linux-x86-64.so.2
(映射到/lib/x86_64-linux-gnu/ld-2.24.so
当前)在 64 位 x86 上的 Debian 9 上,本身由内核加载,内核还加载主可执行文件; - 动态加载、静态链接:据我所知,这在 Linux 上没有使用;
- 动态加载、动态链接:加载器是一个库,例如
libdl
;链接器分为库和调用的程序libdl
。
也许需要对最后一点进行更多解释。当程序使用libdl
加载库时,它会调用dlopen
,它加载命名库及其进程中尚不可用的任何依赖项,并将命名库与其依赖项链接起来。因此libdl
执行加载(必要的库)和链接(仅库,而不是调用程序)。当调用程序需要使用命名库中的符号时,它会调用dlsym
它返回所请求符号的地址(如果可以找到它)。因此,调用程序执行部分链接。
execve
或不存在先有鸡还是先有蛋的问题dlopen
。编译使用的程序是使用对(其中包含大多数程序实际使用的包装器)和符号(严格来说,前面提到的包装器)的execve
适当引用进行编译的。这些引用要么在编译时(对于静态链接程序)要么在加载时(对于动态链接程序)解析;之后,该符号就可以使用并且程序可以调用.这同样适用于:要使用的程序是通过对和 的适当引用进行编译的。动态链接器本身是静态二进制文件,因此内核无需动态链接器的帮助即可加载它。您将在以下位置找到有关此主题的更多详细信息libc
execve
execve
dlopen
dlopen
libdl
dlopen
程序如何运行和程序如何运行:ELF 二进制文件。
(请注意,在所有动态情况下链接,如果启用了延迟绑定,则链接可以即时发生,而不一定在加载时发生。)