1. 写时复制
PAGE_WRITECOPY和PAGE_EXECUTE_WRITECOPY这两个保护属性存在的目的是为了节省内存和使用页交换文件。Windows支持一种机制,允许两个或两个以上的进程共享同一块存储器。让应用程序实例共享相同的存储页极大地提升了系统的性能,但另一方面,也要求所有的应用程序实例只能读取其中的数据 或是执行其中的代码。如果某个应用程序实例修改并写入一个存储页,则是等于修改了其它应用程序实例正在使用的存储页,导致混乱。为了避免这种混乱,操作系统会给共享的存储页指定“写时复制”的属性。通常,包含代码的页面被标记为PAGE_EXECUTE_READ,而包含数据的页面被标记为PAGE_READWRITE.
当线程试图写入一个共享页面时,操作系统会介入并执行下面的操作:
1)系统在内存中找到一个闲置页面。该闲置页面的后备页面来自页交换文件,它是系统最初将模块映射到进程的地址空间时分配的。由于系统在第一次进行映射的时候分配了所有可能需要的页交换文件空间,这一步不可能失败。
2)系统把线程想要修改的页面内容复制到在第1)步中找到的闲置页面。系统会给该闲置页面指定PAGE_READWRITE或PAGE_EXECUTE_READWRITE保护属性,系统不会对原始页面的保护属性和数据做任何修改。
3)然后,系统更新进程的页面表, 这样一来,原来的虚拟地址就对应到了内存中一个新的页面了。
系统在执行这些步骤之后,进程就可以说它自己的副本了。此外,在预订的地址空间或调拨物理存储器,不能使用PAGE_WRITECOPY或PAGE_EXECUTE_WRITECOPY保护属性,否则会导致调用VirtualAlloc失败。