我正在研究创建'模型'的代码。模型是从XML文件创建的,其部分表示是动态生成的C代码。这个C代码在运行时被编译成一个动态加载的共享库(使用POCO共享库类)。共享库主要包含小函数,模型创建的一部分是填充函数指针到这些函数。这一切都很好。但是,同时创建多个模型会导致问题。
我认为它与动态加载在Linux上的工作方式有关,以及每个共享库包含具有相同名称的函数的事实。 PIC会导致这种情况吗?问题表明,从共享库函数中检索数据无论如何。
所以问题是,如何在linux上加载包含相同函数名的多个(数千个)共享库?
以上在Windows上运行良好,似乎动态加载的库数据/函数彼此完全隔离。
答案 0 :(得分:3)
首先,您可以dlopen
数十万个共享对象。我的manydl.c证明了这一点。
然后,您还可以从同一进程生成C代码,编译它和dlopen
共享对象。我(2017年已经过时)MELT plugin(对于GCC,MELT提供了一种扩展GCC的高级语言)这样做(我的manydl.c
示例也是如此)。
但是,我认为您不应该在其中保留相同(已定义)的函数名称。我建议避免这样做。你可以
生成唯一名称(因为生成C代码,这是最好,最便携,最简单的解决方案)
使用一些-D
标志将这些名称编译成#define
个唯一的名称,因此源代码显然可能包含重复的名称;也就是说,如果您生成的代码定义foo
函数将-Dfoo=foo_123
(foo_123
全局唯一)传递给编译它的gcc
命令。 (当然,你dlsym
代表"foo_123"
。
在生成的代码中添加visibility("hidden")个函数属性。您也可以将-fvisibility=hidden
option传递给gcc
。
只有静态函数(然后,名称无关紧要,因此可以重复),并且有一个constructor
函数以某种方式绑定函数(例如将它们的指针存储在某处,例如某些全球表)。
您可以考虑将RTLD_LOCAL
传递给dlopen(3)。我不确定这是个好主意(POCO可能不知道该怎么做)。
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标志解决了问题。