4、进程的内存空间<?xml:namespace prefix = o />
1)进程虚拟地址空间的实现
Windows系统中每个进程都有一个私有的虚拟地址空间,系统需要将每个进程的虚拟地址都映射到物理内存地址上。为了实现系统中每个进程都有一个私有的虚拟地址空间,系统为每一个进程都创建一个页目录( Directory)和一组页表。每个进程的页表是独立的,而内核空间的页表是所有进程共享的。
在x86平台上,CR3寄存器标识了页目录所在的物理地址。Windows系统上的第一个进程都有独立的页目录,因此系统运行时,CR3寄存器中保存的页目录地址是会变化的,其值为当前运行的进程的页目录地址。当系统要进行进程切换时,会将CR3寄存器中保存的页目录地址设置为将要切换过去并开始运行的进程的页目录地址。Windows平台的每一个进程都有一个KPROCESS结构的数据块,其中包括了其进程页目录的地址。
2)数据共享与保护
有一些进程间共享的数据、系统的可执行代码(系统DLL)等,在各个进程间都是一致的,因此没有必要在物理内存中为这些数据保存多份,不同进程的虚拟内存分页可以映射为同样的物理内存分页,这样可以节省物理内存的使用。
同时,为了保证这种在映射到相同物理内存页上的内存分页在进程上仍然是私有的,系统还提供了一些保护机制。如果某个进程将某个系统DLL加载入进程内存空间以后,对该DLL中的数据进行了写操作,系统就会监视到该操作,并在数据写入之前,将要写入的进程虚拟内存分页映射到另一个新的物理分页,并将原分页中系统DLL的内容复制到这个分页中,进程间不共享这个新物理内存分页,最后进程完成写操作,将数据写入这个新分页中。这种对内存中系统DLL数据的写入操作不会影响到其他进程,因此保护了各个进程中数据的独立性,这种机制叫Copy-On-Write。如果系统确实需要在进程间共享数据,也可以对特定的页面不使用Copy-On-Write。
3)注意点
开发人员只需要了解以下内容。
(1)虚拟地址空间中的数据是分页管理的。
(2)应用程序不用考虑系统中其他应用程序的内存使用情况,如占用了多少内存、占用了哪些内存等。
(3)虚拟地址并不是物理地址空间中的地址,不是数据在内存中真实存在的地址,操作系统会将进程的虚拟地址映射到真实的物理内存的地址。
(4)进程也不用考虑真实的物理内存有多大,只需要了解可以使用2GB(一般情况下)的内存,操作系统负责转换。
(5)如果系统中没有足够的物理内存供使用,那么操作系统会将当前没有使用的内存分页“调度”到硬盘上保存起来。页面调度不会造成内存中的数据在虚拟地址空间中地址的改变,所以进程不需要知道内存分页是如何调度的,不需要知道内存中保存的数据是在内存中还是在硬盘上,只需要知道其虚拟地址就可以了。
5、虚拟内存布局、内存的分工
进程的虚拟内存空间分为两个部分,低2GB(或3GB)由应用程序使用,高2GB(或1GB)由系统内核程序使用。
系统内核的内存空间中包括驱动程序,系统内核可执行程序、用于内存管理的数据结构(页目录、页表等),用于进程管理、线程调度的数据结构、各种中断处理程序,系统缓存等。
应用程序可使用的低地址空间中包括了应用程序的代码、数据(全局变量等)、系统和用户DLL的代码、各线程的栈、堆等。
栈和堆是两种重要的内在管理形式。
进程的每个线程都有自己的栈,栈与函数的调用、执行和返回及局部变量的保存相关,一般情况下,栈中保存着函数的参数、返回地址和局部变量,调用函数将参数入栈,调用指令将函数返回地址入栈,被调用函数负责保存调用函数的相关栈指针,为局部变量分配空间等,而堆是一种可以动态分配和释放的内存,由堆管理器进行管理,用户在程序中使用的内存分配函数都是通过堆进行分配的。
6、内存的保护属性和存取权限
系统为每个内存分页提供保护属性和存取权限,内存的保护属性和存取权限的最小单位是分页,同一个分页中的内存具有相同的保护属性和存取权限。用户地址空间中内存分页有多种保护属性和存取权限,如PAGE_EXECUTE等。
http://msdn.microsoft.com/en-us/library/aa366786%28VS.85%29.aspx
7、相关API