假设我在文件spec_a.h中定义了api(sym1) 在lib_imp1.so中有一个这个api的实现。 我可以有一个dlopen这个共享库的应用程序,dlsym()sym1并调用它。是否可以将应用程序dlopen()与sym1作为未定义的其他共享库,并将其解析为lib_imp1.so中的sym1? 如果是这样,我们该怎么做?
如果可能的话,我们可以有两个实现,lib_imp1.so和lib_imp2.so,它们都有两个不同的地址用于相同的符号sym1。 如果应用程序使用未解析的sym1加载另一个共享库,我们是否可以控制哪个sym1(lib_imp1.so或lib_imp2.so)被解析?
在生成lib_imp1.so时,我们可以说虽然我们想要导出sym1,但我们不希望任何未解析的符号被解析出来吗? (有点受控制的出口?)
感谢
答案 0 :(得分:1)
我可以拥有一个dlopen这个共享库的应用程序,dlsym()sym1并调用它。是否可以将应用程序dlopen()与sym1作为未定义的其他共享库,并将其解析为lib_imp1.so中的sym1?
是:如果第一个dlopen
使用RTLD_GLOBAL
,则从lib_imp1.so
(包括sym1
)导出的所有符号都会输入到全局范围内,并对其他人可见库加载了以后。
如果可能,那么我们可以有两个实现,lib_imp1.so和lib_imp2.so,它们都有两个不同的地址用于相同的符号sym1。
是。这是不明智的。
如果应用程序使用未解析的sym1加载另一个共享库,我们是否可以控制哪个sym1(lib_imp1.so或lib_imp2.so)被解析为?
没有。假设您dlopen
同时lib_imp1.so
和lib_imp2.so
同时使用RTLD_GLOBAL
,则任何后续库将始终从第一个sym1
ed库绑定到dlopen
提供它(即它将解析为lib_imp1.so
定义)。
此外,如果lib_imp1.so
也导出sym2
以及lib_imp2.so
调用sym2
中的任何内容,该符号也将解析为内部定义lib_imp1.so
(除非您特别小心并使用-Bsymbolic
)。
最终结果是UNIX .so
库的行为与归档库非常相似,而不像windows DLL
。这使得两个单独的实现导出相同的接口在一个进程中基本上不可行。
在生成lib_imp1.so时,我们可以说虽然我们希望导出sym1,但是我们不希望将任何未解析的符号解析为它吗?
dlsym
使用完全相同的解决方案流程。如果您使该符号无法解析,则dlsym
也找不到该符号。相反,导出符号意味着“使其可用于解析”(通过dlopen
或只是常规未解析的依赖关系解析)。