ash*_*ish 2 dll linker multithreading dynamic-linking dlopen
我正在使用一个共享库,它有相当多的全局变量,几乎在所有导出函数中使用,因此库函数不是线程安全的。我的应用程序创建多个线程,每个线程动态打开该库,并且为了避免在对导出函数的并行调用之间使用任何同步,我在磁盘上以不同的名称多次复制该库,每个线程打开自己的副本。为了避免这种情况,现在我想改用 dlmopen,但我遇到了一个问题。
当我在应用程序中使用 dlopen 打开库时,该应用程序运行良好
libHandle = dlopen(ip->pathname, (RTLD_LAZY |RTLD_LOCAL|RTLD_DEEPBIND|RTLD_NODELETE));
Run Code Online (Sandbox Code Playgroud)
当我在应用程序中使用 dlmopen 时,出现错误:
ip->libHandle = dlmopen(LM_ID_NEWLM, ip->pathname,
(RTLD_LAZY |RTLD_LOCAL|RTLD_DEEPBIND|RTLD_NODELETE));
Run Code Online (Sandbox Code Playgroud)
dl错误是:
error(libfoo.so.0: undefined symbol: _ZTIN6google8protobuf11MessageLiteE)
Run Code Online (Sandbox Code Playgroud)
执行 nm 确实显示符号未定义 U _ZTIN6google8protobuf11MessageLiteE
问题 1:我想知道如何解决这个问题,以便我可以使用 dlmopen。
原因是因为当使用 LM_ID_NEWLM 时,会在 libc 中创建一个没有任何符号的新空命名空间。因此,该库应该是自包含的或与任何依赖项重新链接。
问题 2:我的主应用程序导出 libfoo 将使用的一些符号。由于在新的命名空间中打开 libfoo,主应用程序的符号对 libfoo 不可见,因此无法解析它们。有什么方法可以告诉链接器通过复制现有的基本命名空间来创建新的命名空间 NEWLM ,然后使用新创建的命名空间的 dlmopen + lmid 来打开 libfoo ,并且所有其他必需的符号都已存在?
问题 3:我可以自己映射 libfoo 的不同部分,并提供指向 libc 的映射部分的指针吗?意味着承担打开文件并将其从 libc 映射出来的工作,并让它完成符号解析的工作?这样我根本不需要调用 dlopen 并且多个文本部分的问题将得到解决。
\n\n\n有什么方法可以告诉链接器通过复制现有的基本命名空间来创建新的命名空间 NEWLM ,然后使用新创建的命名空间的 dlmopen + lmid 来打开 libfoo ,并且所有其他必需的符号都已存在?
\n
这是我解决类似问题的方法:
\n\n动态地将 protobuf 加载到新的命名空间中:
\n\nvoid* pb_handle = dlmopen(LM_ID_NEWLM, "libprotobuf.so", RTLD_LAZY);\nRun Code Online (Sandbox Code Playgroud)获取命名空间 ID:
\n\nLmid_t lmid;\ndlinfo(dl_handle, RTLD_DI_LMID, &lmid);\nRun Code Online (Sandbox Code Playgroud)在新的 protobuf 命名空间中打开 foo:
\n\nvoid* foo_handle = dlmopen(lmid, \xe2\x80\x9clibfoo.so.0\xe2\x80\x9d, RTLD_LAZY);\nRun Code Online (Sandbox Code Playgroud)