我正在研究 Windows 系统内部结构,这个问题只是一个猜测。
我了解到 DLL 是一种共享库形式,因此至少同一 DLL 的代码部分在使用它的进程之间共享。 (通过在这些进程的页表中添加相同的页条目)代码部分通常有类似跳转表的东西,需要在准备执行之前重新定位(即写入运行时虚拟地址以修复指针) .
假设相同的 DLL aa.dll
映射到不同虚拟地址的两个不同进程中。 (例如 a.exe
0x00400000 b.exe
0x00410000)相同的指针(在 .text+0x100
处)将被固定到不同的地址。 (例如 a.exe
0x00400100 b.exe
0x004100100)。因此,我们必须复制代码部分并对其进行更改以适应一个过程。那么代码段如何共享呢?
我对吗?
最佳答案
回答我自己的问题。第一次加载 DLL 时,Windows 会尝试将它加载到不需要重定位的首选地址(即由于代码段位于 x 处而修复地址)。如果无法在首选地址加载它,则会在由 DLL 文件本身(不是交换文件)备份的空闲地址分配虚拟页面,但标记为 Copy-On-Write。现在 Windows 必须使用重定位表修复汇编代码。希望只需要修复一小部分代码,并且每个更改的代码段都会在写入时复制并放入物理内存中的某处。
每次进程无法在首选地址加载 DLL 时,我相信这个过程会发生。这就是为什么有时需要重新定位流行的 DLL 以便它们的首选地址不会冲突的原因。
关于windows - 是否保证在每个使用它的进程中将相同的 DLL 映射到相同的虚拟地址?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43613245/