在linux上加载多个类似的共享库

时间:2013-02-28 18:12:25

标签: c++ linux gcc ld

我正在研究创建'模型'的代码。模型是从XML文件创建的,其部分表示是动态生成的C代码。这个C代码在运行时被编译成一个动态加载的共享库(使用POCO共享库类)。共享库主要包含小函数,模型创建的一部分是填充函数指针到这些函数。这一切都很好。但是,同时创建多个模型会导致问题。

我认为它与动态加载在Linux上的工作方式有关,以及每个共享库包含具有相同名称的函数的事实。 PIC会导致这种情况吗?问题表明,从共享库函数中检索数据无论如何。

所以问题是,如何在linux上加载包含相同函数名的多个(数千个)共享库?

以上在Windows上运行良好,似乎动态加载的库数据/函数彼此完全隔离。

2 个答案:

答案 0 :(得分:3)

首先,您可以dlopen数十万个共享对象。我的manydl.c证明了这一点。

然后,您还可以从同一进程生成C代码,编译它和dlopen共享对象。我(2017年已经过时)MELT plugin(对于GCC,MELT提供了一种扩展GCC的高级语言)这样做(我的manydl.c示例也是如此)。

但是,我认为您不应该在其中保留相同(已定义)的函数名称。我建议避免这样做。你可以

  1. 生成唯一名称(因为生成C代码,这是最好,最便携,最简单的解决方案)

  2. 使用一些-D标志将这些名称编译成#define个唯一的名称,因此源代码显然可能包含重复的名称;也就是说,如果您生成的代码定义foo函数将-Dfoo=foo_123foo_123全局唯一)传递给编译它的gcc命令。 (当然,你dlsym代表"foo_123"

  3. 在生成的代码中添加visibility("hidden")个函数属性。您也可以将-fvisibility=hidden option传递给gcc

  4. 只有静态函数(然后,名称无关紧要,因此可以重复),并且有一个constructor函数以某种方式绑定函数(例如将它们的指针存储在某处,例如某些全球表)。

  5. 您可以考虑将RTLD_LOCAL传递给dlopen(3)。我不确定这是个好主意(POCO可能不知道该怎么做)。

  6. PS。我不认为它与position independent code有关(在共享对象中这是优选的,但不是绝对必需的;没有-fPIC dlopen将不得不进行大量低效的重定位) 。它与Linux共享对象链接有关。加载。请阅读Levine's Linkers & Loaders book了解详情。

    另请参阅this question,并阅读Drepper's paper on How to Write Shared Libraries

答案 1 :(得分:3)

Poco SharedLibrary open函数接受链接器标志。默认值为Poco :: SharedLibrary :: SHLIB_GLOBAL,对应于dlopens RTLD_GLOBAL和Poco :: SharedLibrary :: SHLIB_LOCAL,对应于RTLD_LOCAL。有关详细信息,请参阅http://linux.die.net/man/3/dlopen

传递Poco :: SharedLibrary :: SHLIB_LOCAL标志解决了问题。