Dlopen是否会创建多个库实例?

2022-06-28 00:00:00 shared-libraries c++ dlopen

在网上搜索后,似乎找不到答案。

当我第一次使用dlOpen时,它似乎比之后的任何时间都要长,包括如果我从一个程序的多个实例运行它。

dlopen是否将SO加载到内存中一次,并让操作系统保存它,以便任何后续调用(即使是来自程序的另一个实例)都指向内存中的同一位置?

那么基本上,运行库的程序的3个实例是否意味着相同.so的3个实例被加载到内存中,或者内存中只有一个实例?

谢谢


解决方案

dlopen是否将SO加载到内存中一次,并让操作系统保存它,以便任何后续调用(即使是来自程序的另一个实例)都指向内存中的同一位置?

从单个进程内对dlopen的多个调用保证不会多次加载库。来自man page:

   If the same shared object is loaded again with dlopen(), the same
   object handle is returned.  The dynamic linker maintains reference
   counts for object handles, so a dynamically loaded shared object is
   not deallocated until dlclose() has been called on it as many times
   as dlopen() has succeeded on it.

第一次调用dlopen时,库被mmap放入调用进程。通常至少有两个单独的mmap调用:.text.rodata部分(通常位于单个RO段中)映射为只读,.data.bss部分映射为读写。

来自另一个进程的后续dlopen执行相同的mmap。但是,操作系统不必从磁盘加载任何只读数据-它只增加已为第一次dlopen调用加载的页面上的引用计数。这就是"共享库"中的共享。

那么基本上,运行库的程序的3个实例是否意味着相同.so的3个实例被加载到内存中,或者内存中只有一个实例?

取决于您所说的"实例"。

每个进程都有自己的一组(动态分配的)运行时加载器结构来描述这个库,每组都包含一个共享库的"实例"(可以在不同的进程中加载到不同的地址)。每个进程还将拥有自己的可写数据实例(使用写入时复制语义)。但只读映射将全部占用相同的物理内存(尽管它们可能出现在每个进程中的不同地址)。

相关文章