表1 3 - 2列出的保护属性都是非常容易理解的,不过最后两个属性需要作一些说明。一个是PA G E _ W R I T E C O P Y,另一个是PA G E _ E X E C U T E _ W R I T E C O P Y。这两个属性的作用是为了节省R A M的使用量和页文件的空间。Wi n d o w s支持一种机制,使得两个或多个进程能够共享单个内存块。因此,如果1 0个N o t e p a d实例正在运行,那么所有实例可以共享应用程序的代码和数据页面。让所有实例共享同样的内存页面将能够大大提高系统的性能,但是这要求所有实例都将该内存视为只读或只执行的内存。如果一个实例中的线程将数据写入内存修改它,那么其他实例看到的这个内存也将被修改,从而造成一片混乱。
为了防止出现这种混乱,操作系统给共享内存块赋予了C o p y - O n - Wr i t e保护属性。当一个. e x e或D L L模块被映射到一个内存地址时,系统将计算有多少页面是可以写入的(通常包含代码的页面标为PA G E _ E X E C U T E _ R E A D,而包含数据的页面则标为PA G E _ R E A D W R I T E)。然后,系统从页文件中分配内存,以适应这些可写入的页面的需要。除非该模块的可写入页面是实际的写入模块,否则这些页文件内存是不使用的。
当一个进程中的线程试图将数据写入一个共享内存块时,系统就会进行干预,并执行下列操作步骤:
1) 系统查找R A M中的一个空闲内存页面。注意,当该模块初次被映射到进程的地址空间时,该空闲页面将被页文件中已分配的页面之一所映射。当该模块初次被映射时,由于系统要分配所有可能需要的页文件,因此这一步不可能运行失败。
【1】
橙色部分是不是这个意思啊:系统发现一个EXE或者DLL文件有N页是可以写入的,那么就在页文件中分配N页内存,然后把EXE或者DLL的那N页数据拷贝到页文件的那N页中去?那如果是这样的话,不可写的部分怎么办?难道直接在RAM中分配内存来容纳?
【2】
红色部分看半天也没明白。为什么RAM中的空闲页面会被页文件中的页面映射?感觉莫明其妙啊?
英文原文:Note that this free page will be backed by one of the pages allocated in the paging file when the module was first mapped into the process's address space.
这个英文中用的是“BACK”不知是什么意思?
那这样的话,橙色部分怎么理解了呢? 当一个. e x e或D L L模块被映射到一个内存地址时,系统将计算有多少页面是可以写入的(通常包含代码的页面标为PA G E _ E X E C U T E _ R E A D,而包含数据的页面则标为PA G E _ R E A D W R I T E)。然后,系统从页文件中分配内存,以适应这些可写入的页面的需要。
感觉从这句话来理解的话,模块被映射的时候,其内部被分成了可以写入的、不可以写入的两个部分。可以写入的部分所对应的物理内存在页文件中,不可以写入的部分所对应的物理内存在哪里没说(不过我想除了页文件,只有RAM了啊)
黄色字部分和unix的fork()系统调用的某些机制没有差别。
我来说一下unix的这种情况:
简单来说就是fork调用会复制调用的父进程来产生子进程。为了节省内存和提高效率,父和子进程的内存内容是一样的,主要是变量和程序的一样,也就是进程的数据段和代码段的一样,其实就是用的同一块的内存!只有实际使用的使用才会实际复制出一个不同的数据段(怎么是实际使用?当然是子进程和父进程的各种数组变量的不同改变了),但是代码段没有必要修改,两个进程代码段是一样的,其实就是同一块内存,实际区别是子进程的fork返回-1,但是父进程的返回创建的进程ID(是子进程的).用一个if判断来执行父子进程不同的代码。
C o p y - O n - Wr i t e,名字就很形象。write是一个动词,copy也是动词,意思就是:在写入的时候copy。不写入内存就共享一个程序的内存就可以了。10个文本程序都不写入没有必要分配10个文本程序的空间,分配一个就好了。一旦开写就copy一个副本来操作。