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个实例被加载到内存中,或者内存中只有一个实例?
取决于您所说的"实例"。
每个进程都有自己的一组(动态分配的)运行时加载器结构来描述这个库,每组都包含一个共享库的"实例"(可以在不同的进程中加载到不同的地址)。每个进程还将拥有自己的可写数据实例(使用写入时复制语义)。但只读映射将全部占用相同的物理内存(尽管它们可能出现在每个进程中的不同地址)。相关文章