尽管 dlclose,动态加载的库仍保持加载状态

djf*_*djf 5 linux dynamic-loading

今天我正在寻找一些关于动态加载器内部深层魔法的启示。我正在对 Linux 上运行的 C++ 应用程序的插件系统进行调试/故障排除。它通过dlopen(RTLD_NOW | RTLS_LOCAL) 加载插件并使用dlclose. 人们可能会想,没什么特别的。

但是,我注意到即使在dlclose成功调用*之后,某些插件仍保持加载状态。我在使用pmap查看正在运行的进程的内存映射后得出了这一结论。一些库会立即从进程内存中删除,而另一些库显然会无限期地徘徊。

继续,dlopen 手册页指出:

函数 dlclose() 减少动态库句柄句柄上的引用计数。如果引用计数降至零并且没有其他加载的库使用其中的符号,则卸载动态库。

这意味着问题归结为这两种可能性;要么引用计数不为零,要么其他加载的库正在使用某些(但不是全部)插件中的符号。

我非常确定(尽管不是 100%)引用计数为零。应用程序的插件管理器以完全相同的方式处理所有插件。它还确保插件不会被多次加载。因此,IMO 加载和卸载对于所有插件来说应该表现相同。

这就留下了第二种可能性:其他加载的库正在使用插件中的符号。另一个“不应该发生这种事”的典型案例。虽然这当然是可能的。我们正在使用 gcc 和默认可见性,据我所知,没有任何内容被删除,因此正在导出大量符号。实际上这让我更担心,因为这些插件应该是独立的。

以下是我目前的未决问题:

  • 到目前为止我的结论正确吗?
  • dlopen您知道验证引用计数的方法吗?
  • 如果我的插件的内部符号(意外地)被其他库使用,有没有办法追踪谁在使用哪些符号?

我的机器是: Linux 3.13.0-43-generic #72-Ubuntu SMP Mon Dec 8 19:35:44 UTC 2014 i686 i686 i686 GNU/Linux

*我应该提到的是,所有的加载和卸载都发生在主线程中,所以这里应该不存在多线程问题。

Max*_*kin 1

其他加载的库正在使用插件中的符号

如果其他库在链接时未链接到该共享库,则引用共享库的符号不会阻止卸载该共享库。

要调试运行时链接器,请将环境变量 LD_DEBUG 设置为 all,例如LD_DEBUG=all ./my_app. man ld.so详情请参阅。