问题描述
我阅读了一些使用 -fPIC 参数编译的共享库文档,.so 的 .text 段将在进程 fork 的动态链接阶段共享(例如,进程会将 .so 映射到相同的物理地址)
I read some documents that share library comiled with -fPIC argument,the .text seqment of the .so will be shared at process fork's dynamic linking stage(eq. the process will map the .so to the same physical address)
我对谁(内核或 ld.so )以及如何实现这一点感兴趣?也许我应该追踪代码,但我不知道从哪里开始.
i am interested in who (the kernel or ld.so ) and how to accomplish this?maybe i should trace the code, but i dont know where to start it.
尽管如此,我还是尝试验证该声明.
我决定检查 libc.so 中的 printf 之类的函数地址,以便所有 c 程序都将链接.我得到了进程的printf虚拟地址,需要得到物理地址.尝试编写内核模块并将地址值传递给内核,然后调用 virt_to_phys.但它不起作用,因为 virt_to_phys 仅适用于 kmalloc 地址.
Nevertheless, i try to verify the statement.
I decide to check the function address like printf which is in the libc.so that all c program will link.I get the printf virtual address of the process and need to get the physical address. Tried to write a kernel module and pass the address value to kernel, then call virt_to_phys. But it did not work cause the virt_to_phys only works for kmalloc address.
因此,进程页表查看可能是找到虚拟地址到物理地址的映射的解决方案.有没有办法做页表查看?或者其他方式可以适应验证实验?
So, process page table look-at might be the solution to find the virtual address map to physical address. Were there any ways to do page table look-at? Or othere ways can fit the verify experiment?
提前致谢!
推荐答案
动态加载器使用具有 MAP_PRIVATE 和适当权限的 mmap(2)
.您可以通过从 strace -e file,mmap
运行命令来查看它究竟做了什么.例如:
The dynamic loader uses mmap(2)
with MAP_PRIVATE and appropriate permissions. You can see what it does exactly by running a command from strace -e file,mmap
. For instance:
strace -e file,mmap ls
所有的魔法都来自mmap(2)
.mmap(2)
在调用过程中创建映射,它们通常由文件或交换(匿名映射)支持.在文件支持的映射中,MAP_PRIVATE 意味着对内存的写入不会更新文件,并导致该页面从该点开始被交换支持(写入时复制).
All the magic comes from mmap(2)
. mmap(2)
creates mappings in the calling process, they are usually backed either by a file or by swap (anonymous mappings). In a file-backed mapping, MAP_PRIVATE means that writes to the memory don't update the file, and cause that page to be backed by swap from that point on (copy-on-write).
动态加载器从 ELF 的程序头中获取它需要的信息,您可以使用以下方式查看:
The dynamic loader gets the info it needs from ELF's program headers, which you can view with:
readelf -l libfoo.so
从这些中,动态加载器确定将什么映射为代码、只读数据、数据和 bss(文件中大小为零的零填充段,内存中的非零大小,以及仅在隐秘性中匹配的名称)Lisp 的车和 cdr).
From these, the dynamic loader determines what to map as code, read-only data, data and bss (zero-filled segment with zero size in file, non-zero size in memory, and a name only matched in crypticness by Lisp's car and cdr).
因此,事实上,代码还有数据是共享的,直到写入导致写入时复制.这就是为什么将常量数据标记为常量是一个潜在的重要空间优化(参见 DSO howto).
So, in fact, code and also data is shared, until a write causes copy-on-write. That is why marking constant data as constant is a potentially important space optimization (see DSO howto).
您可以在 mmap(2)
手册页和 Documentation/nommu-mmap.txt(MMU 案例,no-MMU 适用于嵌入式设备,如 ADSL 路由器和 Nintendo DS).
You can get more info on the mmap(2)
manpage, and in Documentation/nommu-mmap.txt (the MMU case, no-MMU is for embedded devices, like ADSL routers and the Nintendo DS).
这篇关于共享库如何被不同进程共享?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!