同一进程内两次dlopen同一共享库是否共享数据段变量?
Linux下同一进程多次dlopen同个共享库的地址映射问题解答
核心结论
- 同一进程内两次调用
dlopen加载同一路径的共享库时,二者的数据段会映射到同一内存地址,你的需求完全可以实现。 - 你给出的测试代码逻辑成立,第二次通过
dlsym读取到的var_name值就是首次写入的INIT_VALUE。
原理说明
Linux动态链接器ld.so会为每个已加载的共享库维护加载引用计数:
- 首次调用
dlopen时,动态链接器会完成共享库的内存映射、重定位等完整加载流程,将引用计数置为1 - 后续再次调用
dlopen加载同一个共享库时,不会重新映射内存,仅将引用计数加1,返回的句柄虽可能与首次不同,但查询到的符号地址完全一致
注意事项
- 两次
dlopen传入的共享库路径必须完全一致,避免出现软链接、相对路径解析后指向同文件但路径参数不同的情况,否则动态链接器会判定为不同库,重复加载导致数据段不共享 dlopen的标志位不影响同库符号地址的一致性,即使用RTLD_LOCAL,两次查询到的全局变量地址仍然相同,仅会限制该符号不暴露给其他加载的共享库使用- 调用
dlclose时仅会递减引用计数,计数归0才会真正卸载共享库,首次调用dlclose后,第二次拿到的句柄仍然有效。
标准测试代码示例
#include <dlfcn.h> #include <stdio.h> #define INIT_VALUE 200 // 自定义初始值 int main() { // 首次加载共享库 void* hdl0 = dlopen("./foo.so", RTLD_LAZY); if (!hdl0) { printf("dlopen hdl0 failed: %s\n", dlerror()); return 1; } int* var0 = (int*)dlsym(hdl0, "var_name"); *var0 = INIT_VALUE; printf("var0 address: %p, value: %d\n", var0, *var0); // 第二次加载共享库 void* hdl1 = dlopen("./foo.so", RTLD_LAZY); if (!hdl1) { printf("dlopen hdl1 failed: %s\n", dlerror()); return 1; } int* var1 = (int*)dlsym(hdl1, "var_name"); printf("var1 address: %p, value: %d\n", var1, *var1); // 此处var0和var1地址相同,*var1等于INIT_VALUE dlclose(hdl0); dlclose(hdl1); return 0; }
编译时需要链接dl库:gcc test.c -o test -ldl
内容的提问来源于stack exchange,提问作者wanglongjin
相关产品推荐
相关产品推荐

