Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/70.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 什么时候在程序和共享库之间执行动态链接?_C_Linker_Shared Libraries_Dynamic Linking - Fatal编程技术网

C 什么时候在程序和共享库之间执行动态链接?

C 什么时候在程序和共享库之间执行动态链接?,c,linker,shared-libraries,dynamic-linking,C,Linker,Shared Libraries,Dynamic Linking,在C语言中,程序和共享库之间的动态链接何时执行: 一旦将程序加载到内存中,但在执行程序的main()之前,或 执行程序的main()后,何时执行库中对例程的第一次调用?当第二次或第三次或。。。是否执行从库中调用例程 我一直在想第一句话,直到我读到下面的引语,现在我不确定 不确定操作系统是否重要,我正在使用Linux 从操作系统概念来看: 通过动态链接,图像中会包含一个存根 图书馆-常规参考。存根是一小段代码 指示如何找到适当的内存驻留库 例程或如果尚未加载该例程,则如何加载库 现在 执行存根

在C语言中,程序和共享库之间的动态链接何时执行:

  • 一旦将程序加载到内存中,但在执行程序的
    main()
    之前,或

  • 执行程序的
    main()
    后,何时执行库中对例程的第一次调用?当第二次或第三次或。。。是否执行从库中调用例程

我一直在想第一句话,直到我读到下面的引语,现在我不确定

不确定操作系统是否重要,我正在使用Linux

从操作系统概念来看:

通过动态链接,图像中会包含一个存根 图书馆-常规参考。存根是一小段代码 指示如何找到适当的内存驻留库 例程或如果尚未加载该例程,则如何加载库 现在

执行存根时,它会检查所需的例程是否已在内存中。如果不是,程序将加载 将例行程序存入内存。无论哪种方式,存根都会用 例程的地址,并执行例程。因此,下次 到达该特定代码段时,库例程 直接执行,不产生动态链接成本。在此情况下 方案中,所有使用语言库的进程只执行一个 库代码的副本

我一直在想第一句话,直到我读到下面的引语,现在我不确定

这很复杂(具体取决于你所谓的“动态链接”)

Linux内核将
a.out
加载到内存中。然后检查
PT_INTERP
段(如果有)

如果该段不存在,则二进制文件被静态链接,内核将控制权转移到
Elf{32,64}Ehdr.e_条目
(通常是
\u start
例程)

如果存在
PT_INTERP
段,内核将其加载到内存中,并将控制权转移到它的
.e_条目
。动态链接就是在这里开始的

动态加载程序重新定位自身,然后在
a.out
s
PT\u dynamic
段中查找关于其他必要内容的说明

例如,它通常会找到一个或多个所需的
dtu
条目——直接链接到
a.out
的共享库。加载程序加载任何这样的库,初始化它们,并解析它们之间的任何数据引用

如果
a.out
s
PT\u DYNAMIC
具有
DT\u标志
条目,并且如果该条目包含
DF\u BIND\u NOW
标志,则来自
a.out
的函数引用也将被解析。否则(假设环境中未设置
LD\u BIND\u NOW
),将执行惰性
PLT
解析(解析函数作为对任何给定函数的第一次调用的一部分)。细节

执行存根时,它会检查所需的例程是否已在内存中。如果不是,则程序将例程加载到内存中

我不知道您引用的是哪本书,但当前的UNIX操作系统都不是这样工作的。

操作系统(以及编译器等)当然很重要:语言本身对动态库(以及一般的链接)没有什么可说的。即使我们知道动态链接正在发生,严格一致的程序也无法从其翻译单元之间的计时中观察到任何影响(因为非局部初始化)


这是,Linux上的常用工具链在加载动态库(实现C++等方面)时支持。可执行文件及其所依赖的动态库(通常用

-l
指定)允许每个模块中的初始化(成功地)使用其依赖项中的函数。(在某些情况下是有顺序的。)当然,可以用于以后加载和初始化更多库。

在Linux中,就在
main()之前。
。ELF文件(二进制文件和库)可以将函数标记为“构造函数”或“析构函数”,它们分别在
main()
之前和最后一个线程退出之后运行。我相信构造器是在所有库都被映射之后运行的,按照优先级的递增顺序(101到65535,包括101到65535),但我不确定顺序。(虽然我知道它们都是在
main()
启动之前运行的。)但是,还有一个等,它也可以随时进行动态链接。