4

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

我相信这与动态加载在 Linux 上的工作方式有关,以及每个共享库都包含具有相同名称的函数这一事实。PIC会导致这个吗?这些问题毫无意义地表现在从共享库函数中检索数据。

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

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

4

2 回答 2

3

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

然后,您还可以生成 C 代码、编译它和dlopen共享对象,所有这些都来自同一个进程。我的(2017 年过时)MELT 插件(对于 GCC,MELT 提供了一种高级语言来扩展 GCC)(我的manydl.c示例也是如此)。

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

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

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

  3. 在生成的代码中添加可见性(“隐藏”)函数属性。您也可以将-fvisibility=hidden 选项传递给gcc.

  4. 只有静态函数(然后,名称并不重要,所以可以重复),并且有一个constructor以某种方式绑定函数的函数(例如将它们的指针存储在某个地方,例如在某个全局表中)。

  5. 您可以考虑传递RTLD_LOCALdlopen(3)。我不确定这是一个好主意(而且 POCO 可能不知道该怎么做)。

PS。我不认为它与位置无关代码有关(在共享对象中这是可取的,但不是绝对必需的;如果没有-fPICdlopen将不得不做很多低效的重定位)。它与 Linux 共享对象链接和加载有关。有关详细信息,请阅读Levine 的 Linkers & Loaders 书

另请参阅此问题,并阅读Drepper 关于如何编写共享库的论文。

于 2013-02-28T18:31:08.193 回答
3

Poco SharedLibrary 打开函数接受链接器标志。默认为 Poco::SharedLibrary::SHLIB_GLOBAL,对应 dlopens RTLD_GLOBAL 和 Poco::SharedLibrary::SHLIB_LOCAL,对应 RTLD_LOCAL。有关更多信息,请参见http://linux.die.net/man/3/dlopen

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

于 2013-02-28T20:46:50.380 回答