我阅读了一些与-fPIC参数共享库的文档, .so的.text seqment将在process fork的动态链接阶段共享 (例如,该过程将.so映射到相同的物理地址)
我感兴趣的是谁(内核或ld.so)以及如何实现这一目标? 也许我应该追踪代码,但我不知道从哪里开始。
然而,我试图验证声明 我决定检查函数地址,就像libc.so中的printf一样,所有c程序都将链接。 我得到进程的printf虚拟地址,需要获取物理地址。试图写一个内核模块并将地址值传递给内核,然后调用virt_to_phys。但它没有用,因为virt_to_phys仅适用于kmalloc地址。
因此,进程页表查找可能是查找虚拟地址映射到物理地址的解决方案。是否有任何方法可以进行页面表查看?或者其他方式可以适合验证实验?
提前感谢!
答案 0 :(得分:4)
动态加载程序使用mmap(2)
和MAP_PRIVATE以及适当的权限。您可以通过从strace -e file,mmap
运行命令来查看它的确切功能。例如:
strace -e file,mmap ls
所有的魔力来自mmap(2)
。 mmap(2)
在调用进程中创建映射,它们通常由文件或交换(匿名映射)支持。在文件支持的映射中,MAP_PRIVATE意味着对内存的写入不会更新文件,并导致该页面由该点上的交换支持(写时复制)。
动态加载程序从ELF的程序头中获取所需的信息,您可以使用以下命令查看:
readelf -l libfoo.so
从这些中,动态加载器确定要映射的内容为代码,只读数据,数据和bss(文件中零大小的零填充段,内存中的非零大小,以及仅通过隐藏性来匹配的名称Lisp的车和司机。
因此,事实上,代码以及数据是共享的,直到写入导致写时复制。这就是为什么将常数数据标记为常数是一个潜在的重要空间优化(参见DSO howto)。
您可以在mmap(2)
联机帮助页和Documentation/nommu-mmap.txt中获取更多信息(MMU案例中,无MMU适用于嵌入式设备,如ADSL路由器和Nintendo DS)。
答案 1 :(得分:2)
共享库只是映射文件的特定用途。
文件在进程的地址空间中映射的地址与是否共享无关。
即使页面映射到不同的地址,也可以共享页面。
要确定是否共享页面,请执行以下操作:
如果两个进程的页面映射在同一个物理地址,那么它当然是共享的。