有什么方法可以将共享对象文件 (.so) 添加到 ld.so.cache?

Is there a way I can add a shared object file (.so) to ld.so.cache?

我写了一个简单的 C 程序,在共享对象上执行 dlopen:

 handle = dlopen ("./MySharedObject.so", RTLD_LAZY);
        if (!handle) {
            fputs (dlerror(), stderr);
            exit(1);
        }
sleep(20)
dlclose(..)

现在我将我的程序编译为可执行文件,并在同一台机器上同时 运行 可执行文件的多个实例。我认为将在所有 运行 中被 return 编辑的句柄是相同的。但是,似乎 ld.so.cache 中加载的共享对象是唯一可以 return 相同句柄的共享对象。

我的目标是不使用 dlopen 加载相同的代码两次。有人知道如何实现吗?

I thought the handle that will be returned in all the runs will be same.

它不会,但这并不意味着你看起来认为它意味着什么。

即使句柄不同,共享库仍然有效,并且仍然在多个进程之间共享。换句话说,没有问题需要你在这里解决。

But, it seems that the loaded shared objects in the ld.so.cache are the only ones that can return the same handle.

这也是错误的:绝对不能保证 ld.so.cache 中列出的对象将在不同进程中使用相同的句柄。

更新:

I assumed that the handle is pointer to the loaded contents of the shared library.

这是不正确的:在 GLIBC 下,句柄是指向描述特定库的堆分配块的指针。它不指向库本身。

If I dlsym a symbol, it ideally should return the start of where the symbols definition is loaded.

正确。

In this case I get different dlsym values. Does this means that the symbol is loaded twice?

不,不是。通过虚拟内存的魔力,RAM 的相同物理页面可以出现在不同进程的不同地址。当 ASLR 打开时,这对于共享库来说非常常见。

例如,这里是同一个 /bin/date 二进制文件的两次执行:

$ ldd /bin/date | grep libc.so.6
        libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f60ff32f000)
$ ldd /bin/date | grep libc.so.6
        libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007ffa38e2a000)

请注意 libc.so.6 在不同的地址加载(同时仍与系统上当前 运行 的所有 other 进程共享)。

也很容易造成相同物理 RAM 页面出现在单个进程中不同地址的情况:只需对同一个文件描述符调用 mmap(fd, ..., 0) 两次。