共享库如何被不同的进程共享?

我读了一些共享库用-fPIC参数指定的文档,.so的.text部分将在进程fork的dynamic链接阶段共享(例如,进程将把.so映射到相同的物理地址)

我感兴趣谁(内核或ld.so)以及如何完成这个? 也许我应该跟踪代码,但我不知道从哪里开始。

尽pipe如此,我试图validation这个说法。
我决定检查函数地址,如printf,它位于libc.so中,所有的c程序都会链接。 我得到了printf进程的虚拟地址,需要获取物理地址。 试图编写一个内核模块,并将地址值传递给内核,然后调用virt_to_phys。 但它没有工作,因为virt_to_phys只适用于kmalloc地址。

所以,处理页表查找可能是find虚拟地址映射到物理地址的解决scheme。 有没有办法做页表查找? 还是其他方法可以适合validation实验?

提前致谢!

动态加载器使用mmap(2)和MAP_PRIVATE以及适当的权限。 您可以通过从strace -e file,mmap运行命令来查看它的作用。 例如:

 strace -e file,mmap ls 

所有的魔法都来自mmap(2)mmap(2)在调用过程中创建映射,它们通常由文件或交换(匿名映射)支持。 在文件支持的映射中,MAP_PRIVATE意味着写入内存不会更新文件,并使该页面从该点开始交换(copy-on-write)。

动态加载器从ELF的程序头获取所需的信息,您可以使用它来查看:

 readelf -l libfoo.so 

从这些,动态加载器决定什么映射为代码,只读数据,数据和BSS(零填充段文件中的零大小,非零大小的内存中,只有在匹配的隐秘Lisp的汽车和CDR)。

所以,实际上, 代码和数据是共享的 ,直到写入导致写入时复制。 这就是为什么将常量数据标记为常量是一个潜在的重要空间优化(参见DSO howto )。

您可以在mmap(2)联机帮助页上获得更多信息,在Documentation / nommu-mmap.txt (MMU情况下,没有MMU用于嵌入式设备,如ADSL路由器和任天堂DS)。

共享库只是特定的使用映射文件。

文件映射到进程地址空间的地址与共享与否无关。

即使页面映射到不同的地址,也可以共享页面。

要了解页面是否被共享,请执行以下操作:

  1. 通过检查/ proc / pid / maps来查找文件的映射地址
  2. 有一个工具从/ proc / pid / pagemap提取数据 – 找到并使用它。 这给你一个信息,确切地说哪个页面(S)的地图是什么,他们在什么位置

如果两个进程有一个页面映射到同一个物理地址,当然是共享的。