1. 进程地址空间
软件的进程运行于32位系统上,其寻址位也是32位,能表示的空间是232=4G,范围从0x0000 0000~0xFFFFFFFF。
·
NULL指针分区
范围:0x0000 0000~0x0000 FFFF
作用:保护内存非法访问
例子:分配内存时,如果由于某种原因分配不成功,则返回空指针0x00000000;当用户继续使用比如改写数据时,系统将因为发生访问违规而退出。
·
独享用户分区
范围:0x0001 0000~0x7FFE FFFF
作用:进程只能读取或访问这个范围的虚拟地址;超越这个范围的行为都会产生违规退出。
例子:
注意:如果在boot.ini上设置了/3G,这个区域的范围从2G扩大为3G:0x0001 0000~0xBFFEFFFF。
·
共享内核分区
范围:0x8000 0000~0xFFFF FFFF
作用:这个空间是供操作系统内核代码、设备驱动程序、设备I/O高速缓存、非页面内存池的分配、进程目表和页表等。
例子:
注意:如果在boot.ini上设置了/3G,这个区域的范围从2G缩小为1G:0xC000 0000~0xFFFFFFFF。
2. 进程地址空间与实际内存的映射
地址空间在运行中映射为实际的物理页面。
·
区域
区域指的是上述地址空间中的一片连续地址。区域的大小必须是粒度(64k)的整数倍,不是的话系统自动处理成整数倍。不同CPU粒度大小是不一样的,大部分都是64K。
区域的状态有:空闲、私有、映射、映像。
在你的应用程序中,申请空间的过程称作保留(预订),可以用VirtualAlloc;删除空间的过程为释放,可以用VirtualFree。
这时候的区域状态是私有;
默认情况下,区域状态是空闲;
当exe或DLL文件被映射进了进程空间后,区域状态变成映像;
当一般数据文件被映射进了进程空间后,区域状态变成映射。
·
物理存储器
Windows各系列支持的内存上限是不一样的,从2G到64G不等。理论上32位CPU,硬件上只能支持4G内存的寻址;能支持超过4G的内存只能靠其他技术来弥补。顺便提一下,Windows个人版只能支持最大2G内存,Intel使用AddressWindows Extension (AWE) 技术使得寻址范围为236=64G。当然,也得操作系统配合。
·
页文件
页文件是存在硬盘上的系统文件,它的大小可以在系统属性里面设置,它相当于物理内存,所以称为虚拟内存。事实上,它的大小是影响系统快慢的关键所在,如果物理内存不多的情况下。
·
访问属性
物理页面的访问属性指的是对页面进行的具体操作:可读、可写、可执行。CPU一般不支持可执行,它认为可读就是可执行。但是,操作系统提供这个可执行的权限。
PAGE_NOACCESS
PAGE_READONLY
PAGE_READWRITE
PAGE_EXECUTE
PAGE_EXECUTE_READ
PAGE_EXECUTE_READWRITE
这6个属性很好理解,第一个是拒绝所有操作,最后一个是接受收有操作;
PAGE_WRITECOPY
PAGE_EXECUTE_WRITECOPY
这两个属性在运行同一个程序的多个实例时非常有用;它使得程序可以共享代码段和数据段。一般情况下,多个进程只读或执行页面,如果要写的话,将会Copy页面到新的页面。通过映射exe文件时设置这两个属性可以达到这个目的。
PAGE_NOCACHE
PAGE_WRITECOMBINE
这两个是开发设备驱动的时候需要的。
PAGE_GUARD
当往页面写入一个字节时,应用程序会收到堆栈溢出通知,在线程堆栈时有用。
·
映射过程
进程地址空间的地址是虚拟地址,也就是说,当取到指令时,需要把虚拟地址转化为物理地址才能够存取数据。这个工作通过页目和页表进行。
页目大小为4K,其中每一项(32位)保存一个页表的物理地址;每个页表大小为4K,其中每一项(32位)保存一个物理页的物理地址,一共有1024个页表。利用这4K+4K*1K=4.4M的空间可以表示进程的1024*1024*(一页4K) =4G的地址空间。
高10位用来找到1024个页目项中的一项,取出页表的物理地址后,利用中10位来得到页表项的值,根据这个值得到物理页的地址,由于一页有4K大小,利用低12位得到单元地址,这样就可以访问这个内存单元了。
3. 结构体MEMORY_BASIC_INFORMATION
typedef struct _MEMORY_BASIC_INFORMATION{
PVOID BaseAddress;
//查询内存块所占的第一个页面基地址
PVOID AllocationBase;
//内存块所占的第一块区域基地址,小于等于BaseAddress,
//也就是说BaseAddress一定包含在AllocationBase分配的范围内
DWORD AllocationProtect;
//区域被初次保留时赋予的保护属性
SIZE_TRegionSize;
//从BaseAddress开始,具有相同属性的页面的大小,
DWORD State;
//页面的状态,有三种可能值:MEM_COMMIT、MEM_FREE和MEM_RESERVE,
//这个参数对我们来说是最重要的了,从中我们便可知指定内存页面的状态了
DWORD Protect;
//页面的属性,其可能的取值与AllocationProtect相同
DWORD Type;
//该内存块的类型,有三种可能值:MEM_IMAGE、MEM_MAPPED和MEM_PRIVATE
} MEMORY_BASIC_INFORMATION,*PMEMORY_BASIC_INFORMATION;