今天我正在寻找动态装载机内部深层魔法的一些启示。我正在调试/排除在Linux上运行的C ++应用程序的插件系统故障。它通过dlopen
(RTLD_NOW | RTLS_LOCAL)加载插件,并使用dlclose
释放它们。没有什么特别的 - 人们会想。
但是,我注意到即使在成功调用{sup> * dlclose
之后,仍会加载一些插件。在使用pmap查看正在运行的进程内存映射后,我得出结论。有些库会立即从进程内存中删除,而其他库则会无限期地挥之不去。
继续,dlopen man页面说明:
函数dlclose()减少动态的引用计数 库句柄。如果引用计数降为零而不是 其他加载的库在其中使用符号,然后动态库是 卸载。
这意味着问题归结为这两种可能性;引用计数不是零,或者其他加载的库使用来自某些插件(但不是全部)插件的符号。
我很确定(尽管不是100%)引用计数为零。应用程序的插件管理器处理所有插件完全相同。它还确保插件不会多次加载。 IMO loading&因此,对于所有插件,卸载应该表现相同。
这留下了第二种可能性:其他加载的库正在使用插件中的符号。另一个典型案例'应该永远不会发生'。虽然这当然是可能的。我们正在使用gcc和默认可见性,据我所知,没有任何东西被剥离,因此导出了大量的符号。实际上,这让我更加担心,因为这些插件应该是独立的。
此时此处是我的开放性问题:
dlopen
引用计数的方法? 我的机器是: Linux 3.13.0-43-generic#72-Ubuntu SMP Mon Dec 8 19:35:44 UTC 2014 i686 i686 i686 GNU / Linux
* 我应该提到所有的加载和卸载都发生在主线程中,因此这里不存在多线程问题。
答案 0 :(得分:1)
其他已加载的库正在使用插件中的符号
如果其他lib在链接时未链接到该共享库,则引用共享库的符号不会阻止卸载该共享库。
将运行时链接程序集环境变量LD_DEBUG调试为all,例如LD_DEBUG=all ./my_app
。有关详细信息,请参阅man ld.so
。