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

问题描述 投票:0回答:2

今天我正在寻找动态加载器内部深层魔法的一些启示。我正在对 Linux 上运行的 C++ 应用程序的插件系统进行调试/故障排除。它通过

dlopen
(RTLD_NOW | RTLS_LOCAL) 加载插件并使用
dlclose
释放它们。人们可能会想,没什么特别的。

但是,我注意到即使在成功调用

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

继续,dlopen man页面指出:

函数 dlclose() 减少动态引用计数 库句柄句柄。如果引用计数下降到零并且没有 其他加载的库使用了其中的符号,那么动态库是 已卸载。

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

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

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

这是我目前的未决问题:

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

我的机器是: Linux 3.13.0-43-generic #72-Ubuntu SMP 星期一 12 月 8 日 19:35:44 UTC 2014 i686 i686 i686 GNU/Linux

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

linux dynamic-loading
2个回答
1
投票

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

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

要调试运行时链接器,请将环境变量 LD_DEBUG 设置为 all,例如

LD_DEBUG=all ./my_app
。详情请参阅
man ld.so


0
投票

您很久以前就发布了这个问题,并且您可能已经找到了答案,但对其他人来说仍然可能很有趣。我想说你的结论“其他加载的库正在使用插件中的符号”是正确的。系统能够在符号绑定时检测到这一点。 glibc中的相关代码如下(glibc 2.38源代码中的

elf/dl-lookup.c::_dl_lookup_symbol_x()
):

  /* We have to check whether this would bind UNDEF_MAP to an object
     in the global scope which was dynamically loaded.  In this case
     we have to prevent the latter from being unloaded unless the
     UNDEF_MAP object is also unloaded.  */
  if (__glibc_unlikely (current_value.m->l_type == lt_loaded)
      /* Don't do this for explicit lookups as opposed to implicit
         runtime lookups.  */
      && (flags & DL_LOOKUP_ADD_DEPENDENCY) != 0
      /* Add UNDEF_MAP to the dependencies.  */
      && add_dependency (undef_map, current_value.m, flags) < 0)
    ...

这里的相关部分是对

add_dependency()
的调用。

换句话说,在符号查找时,会记录依赖关系。这意味着在其他一些库中,X 使用插件中的符号,那么只有当 X dlclose 时才会卸载插件(这可能只发生在

exit()
)。

关于您的其他问题:

你知道验证 dlopen 引用计数的方法吗?

我不知道有什么方法可以做到这一点。

如果我的插件(不小心)使用了内部符号 其他库,有没有办法追踪谁在使用哪些符号?

LD_DEBUG=bindings
谁能帮忙解决这个问题。

© www.soinside.com 2019 - 2024. All rights reserved.