今天,我正在寻找动力装载机内部深层魔法的一些启示。 我正在debugging/排除在Linux上运行的C ++应用程序的插件系统。 它通过dlopen
(RTLD_NOW | RTLS_LOCAL)加载插件并使用dlclose
释放它们。 没有什么特别的 – 人们会想。
不过,我注意到,即使在成功调用dlclose
之后,一些插件仍然保持加载状态。 我在使用pmap查看正在运行的进程的内存映射之后得出了这个结论。 一些库被立即从进程内存中移除,而另一些则显然无限期地逗留。
继续, dlopen手册页指出:
函数dlclose()递减dynamic库句柄句柄的引用计数。 如果引用计数下降到零,并且没有其他加载的库使用其中的符号,则dynamic库将被卸载。
这意味着问题归结为这两种可能性。 引用计数不为零,或者其他加载的库使用来自某些(而不是全部)插件的符号。
我很确定(虽然不是100%)参考计数为零。 应用程序的插件pipe理器完全相同地处理所有的插件。 它也确保一个插件不会被加载多次。 因此IMO的加载和卸载对于所有的插件都应该是一样的。
这留下了第二种可能性:其他加载的库正在使用来自插件的符号。 另外一个典型的例子,那就是“永远不会发生”。 尽pipe这当然是可能的。 我们正在使用gcc和默认的可见性,据我所见,没有任何东西被剥离,所以吨的符号被导出。 其实这让我感到担心得多,因为这些插件应该是独立的。
在这里,这里是我的开放性问题:
dlopen
的引用计数吗? 我的机器是: Linux 3.13.0-43-generic#72-Ubuntu SMP Mon Dec 8 19:35:44 UTC 2014 i686 i686 i686 GNU / Linux
*我应该提到,所有的加载和卸载都发生在主线程中,所以在这里不应该存在multithreading问题。
其他加载的库正在使用来自插件的符号
如果其他库在链接时未链接到该共享库,则引用共享库的符号不会阻止该共享库被卸载。
调试运行时链接程序设置环境变量LD_DEBUG到全部,例如LD_DEBUG=all ./my_app
。 详见man ld.so