问题描述
当共享库没有被编译为PIC时,它仍然可以通过加载时重定位与可执行文件链接。
如果我理解正确,动态加载器会查找重定位表中列出的条目,并根据内存映射修改它们。即共享库的代码在加载时适应当前进程。
我的问题是,另一个进程如何同时使用同一个共享库,加载程序是否保证两个进程的内存映射一致?或者库无法共享,操作系统只会将共享库的另一个副本加载到内存中?
解决方法
当共享库没有被编译为PIC时,它仍然可以通过加载时重定位与可执行文件链接。
此语句需要限定符:这仅在某些平台上可行(例如 ELF32 ix86),而在其他平台上不可行(例如,具有默认中等内存模型的 ELF64 x86_64)。
动态加载器会查找重定位表中列出的条目,并根据内存映射修改它们。即共享库的代码在加载时适应当前进程。
正确。请注意,加载器必须更新的任何内存页面都将成为非共享。
另一个进程如何同时使用同一个共享库
另一个进程将拥有自己的加载器更新页面的副本,但将与第一个进程共享任何未修改的页面。
加载器是否保证两个进程的内存映射一致?
没有
或者库无法共享,操作系统只会将共享库的另一个副本加载到内存中?
不完全:根据加载器需要修改的页面数量,一些共享仍然可以发生。
附言当您使用 -fPIC
构建共享库时,加载器需要更新的页面数量被最小化(所有需要更新的地方都集中在 .got
部分,而不是将这些地方分散贯穿整个 .text
部分)。