一、进程虚拟地址空间
1、每个进程都有自己的虚拟地址空间。对于32位操作系统来说,它的地址空间是4GB。这是因为32位指针可以表示从0x00000000到0xFFFFFFFF之间的任一值。对于64位的操作系统来说有0到2的64次方之间的任一值。
2、由于每个就进程都有自己的地址空间,因此每个进程都只能访问属于自己的地址空间而不能访问其他进程的空间。这保护了进程,也是之所以我们说进程是资源分配和保护的基本单位的原因。
3、每个进程都有自己的私有地址空间,进程A可以访问它的地址空间0x11009333处的地址。进程B当然也有这个地址,但进程B的此地址处存储的与进程A的数据完全不同。它们没有任何关系。进程A不能访问进程B的地址空间。反之亦然。
4、每个进程的地址空间都被分成多个分区。由于地址空间分区依赖于操作系统底层实现,因此各个版本的Windows的分区各不相同。此处我们主要介绍32位和64位的Windows内核下的分区情况。
一)空指针赋值区
这一分区是进程地址空间从0x00000000到0x0000FFFF的区域。共64KB。该分区的作用是帮助程序员捕获对空指针的赋值。如果进程中的线程试图访问此区域将会导致访问违规。(原因:此区域未调拨空间,访问未调拨空间的地址将会导致访问违规)。这种情况经常由调用API申请空间失败引起,如malloc。但未对指针进行检查。
没有任何方法能够访问到此区域的虚拟内存。
二)用户模式模式分区。
1、这一部分空间是进程地址空间的驻地。它的大小也取决于cpu体系结构。
2、X86cpu体系下的用户模式分区从0x00010000——0x7FFEFFFF总共2GB。进程的大部分数据都保存在这一分区。这其中包括程序加载的dll。
3、有些用户程序需要大于2G的用户模式地址空间。为此Windows提供了一种大用户分区模式来增大用户模式分区,但最多为3GB。要启动大用户分区模式可以查询其他资料,此处不再介绍。
4、当32位的应用程序在64位下的环境下运行时,Windows会让此程序在地址空间沙箱中运行。系统将64位地址的高33位都设为0,这样就截断成了32位地址,也就将可用的地址空间限制在最底部的2GB中。对于大多数的程序来说,2GB的地址空间已经足够,为了让64位应用程序能够访问整个用户模式分区,必须用/LARGEADDRESSAWARE连接器开关来链接应用程序。
三)内核模式分区
1、这一分区是操作系统代码的驻地。系统需要这一部分空间来存放内核代码、设备驱动程序代码、设备输入输出高速缓存、非分页缓冲池分配表、进程页面表等。驻留在这一分区任何东西为所有进程共有,被映射到所有进程地址空间中。如果一个应用程序试图访问这一区域将会导致访问违规。
2、当系统创建一个进程同时为其创建它地址空间时,此地址空间中大部分都是闲置的。为了使用这部分地址空间,我们必须调用VirtualAlloc来分配其中的区域。分配区域的操作被称为预定。
3、当应用程序预定地址空间区域时,系统会确保预定的区域的起始地址正好是分配粒度的整数倍。分配粒度根据不同的CPU平台而有所不同。现在所有的平台都是用相同的分配粒度。大小为64KB。
4、而对于预定的地址空间的大小,系统会确保区