共享库以什么顺序初始化和完成?

时间:2018-10-26 05:03:43

标签: shared-libraries destructor exit dlopen

一个过程中的动态对象来自多个来源:

  1. 可执行文件本身
  2. 它需要的任何库(ELF为DT_NEEDED
  3. 显式加载的库(dlopen或类似的库)
  4. 此类显式负载所需的任何库

它们可以显式dlclose)卸载,也可以隐式卸载,当进程exit运行其终结处理(atexit两种情况下都可以使用这些函数,C ++中的静态持续时间析构函数和__attribute__((destructor))函数。

在这些各种情况下,什么决定动态对象初始化和完成的顺序?显然,库的最后一个dlclose会立即将其卸载,但是其依赖关系树(其中一些还可能是其他已加载库的依赖关系)又如何呢?如果dlopen已创建库,然后exit卸载了库怎么办?

我倾向于期望通常的反向初始化顺序,但是DT_NEEDEDdlopen之间可能会有差异,因为后者会加载“插件”,并且可能预计将取决于可执行文件的数据,而不是相反。

1 个答案:

答案 0 :(得分:1)

在所有情况下,算法都是相同的。映射主要可执行文件(或dlopen ed库)后,动态链接程序将按拓扑顺序执行初始化函数,以便在依赖项之前对依赖项进行初始化。请注意,在某些情况下,这可能使顺序不确定,并且链接器在那里可以任意选择。

库析构函数已在其构造函数之一中注册(通过调用__cxa_atexit)。通过将累积库dtor函数放在Glibc中的特殊列表之前来执行注册。在exit上,该列表是向前遍历的,因此相关的析构函数将在其依赖项之前被调用。