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

时间:2018-06-10 17:23:45

标签: c linker shared-libraries dynamic-linking

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

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

  • 执行程序的main()后,执行从库中第一次调用例程的时间?当执行第二个或第三个或......来自库的例程调用时,是否会再次发生动态链接?

我在想第一个,直到我读到以下引用,现在我不确定。

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

来自操作系统概念:

  

通过动态链接,每个图像中都包含一个存根   图书馆 - 例行参考。存根是一小段代码   指示如何找到适当的内存驻留库   例程或如果例程尚未加载库的方法   当下。

     

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

2 个答案:

答案 0 :(得分:1)

  

我在想第一个,直到我读到以下引用,现在我不确定。

它很复杂(并且完全取决于你所谓的“动态链接”)。

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

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

如果PT_INTERP 存在,则内核将其加载到内存中,并将控制转移到它的 .e_entry。在这里,动态链接开始

动态加载程序重新定位,然后在a.out s PT_DYNAMIC段中查找有关其他必要内容的说明。

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

如果a.out s PT_DYNAMIC有一个DT_FLAGS条目,如果该条目包含DF_BIND_NOW标记,那么 function 引用{{1也将被解决。否则(并假设未在环境中设置a.out),将执行惰性LD_BIND_NOW解析(将函数解析为对任何给定函数的第一次调用的一部分)。详情here

  

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

我不知道你引用哪本书,但当前的UNIX操作系统没有这种方式。

答案 1 :(得分:1)

操作系统(和编译器,等。)当然很重要:语言本身对动态库没什么好说的(和very little一般关于链接)。即使我们知道正在发生动态链接,但严格一致的程序也无法观察到其翻译单元之间的时序效应(因为非本地初始化cannot have side effects)。

也就是说,Linux上的常见工具链在加载动态库时支持automatic initialization(用于实现C ++等)。可执行文件及它们所依赖的动态库(通常用-l指定)是loaded and initialized recursively,以允许在每个模块中初始化(成功)使用其依赖项中的函数。 (在某些情况下,订单会有unfortunate choice。)当然,dlopen(3)可以用来加载和初始化更多的库。