You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

同一进程内两次dlopen同一共享库是否共享数据段变量?

Linux下同一进程多次dlopen同个共享库的地址映射问题解答

核心结论

  • 同一进程内两次调用dlopen加载同一路径的共享库时,二者的数据段会映射到同一内存地址,你的需求完全可以实现。
  • 你给出的测试代码逻辑成立,第二次通过dlsym读取到的var_name值就是首次写入的INIT_VALUE。

原理说明

Linux动态链接器ld.so会为每个已加载的共享库维护加载引用计数:

  1. 首次调用dlopen时,动态链接器会完成共享库的内存映射、重定位等完整加载流程,将引用计数置为1
  2. 后续再次调用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.27 02:36:01