内存保护

属于进程的内存由其专用虚拟地址空间隐式保护。 此外,Windows 使用虚拟内存硬件提供内存保护。 此保护的实现因处理器而异,例如,进程地址空间中的代码页可以标记为只读,并且不受用户模式线程修改的保护。

有关属性的完整列表,请参阅 内存保护常量

写入时复制保护

复制写入保护是一种优化,允许多个进程映射其虚拟地址空间,以便它们共享物理页,直到其中一个进程修改页面。 这是一种称为 延迟评估的技术的一部分,它允许系统在绝对必要之前不执行作来节省物理内存和时间。

例如,假设两个进程将同一 DLL 中的页面加载到其虚拟内存空间中。 这些虚拟内存页映射到这两个进程的相同物理内存页。 只要两个进程都无法写入这些页面,它们就可以映射到和共享相同的物理页面,如下图所示。

进程 1 和 2 页的框和箭头映射到同一物理内存

如果进程 1 写入其中一个页面,则物理页的内容将复制到另一个物理页,并且虚拟内存映射将更新为 Process 1。 这两个进程现在在物理内存中都有自己的页面实例。 因此,一个进程无法写入共享物理页,另一个进程可以查看更改。

进程和物理内存重新映射 的框和箭头

加载应用程序和 DLL

加载同一基于 Windows 的应用程序的多个实例时,每个实例在其自己的受保护虚拟地址空间中运行。 但是,它们的实例句柄(hInstance)通常具有相同的值。 此值表示应用程序的虚拟地址空间中的基址。 如果每个实例都可以加载到其默认基址中,则可以使用写入复制保护映射到其他实例并与其他实例共享相同的物理页。 系统允许这些实例共享相同的物理页面,直到其中一个实例修改页面。 如果出于某种原因,这些实例之一无法加载到所需的基址中,它将接收其自己的物理页。

DLL 是使用默认基址创建的。 使用 DLL 的每个进程都将尝试在其自己的地址空间中加载 DLL,该 DLL 的默认虚拟地址。 如果多个应用程序可以在其默认虚拟地址加载 DLL,则可以共享 DLL 的相同物理页。 如果出于某种原因,进程无法在默认地址加载 DLL,则会在其他地方加载 DLL。 写入时复制保护强制将 DLL 的某些页面复制到此过程的不同物理页中,因为对跳转指令的修复是在 DLL 页中编写的,因此此过程将有所不同。 如果代码节包含对数据节的许多引用,这可能会导致整个代码节复制到新的物理页。