进程的虚拟地址空间
对于32位进程来说,这个地址空间的大小为4GB。每个进程都有自己专有的地址空间,当进程中的各线程运行时,它们只能访问属于该进程的内存。线程既看不到属于其他进程的内存,也无法访问它们。

虚拟地址空间的分区
1、空指针赋值分区:进程地址空间的0x00000000到0x0000FFFF的闭区间。
2、用户模式分区:在x86的CPU中,地址空间为0x00010000到0x7FFEFFFF  ~2GB。所有的exe和DLL都载入到这一区域。
因此进程可用地址空间的数量还不到进程整个地址空间的一半。
在x86模式下,可以得到更大的用户模式分区,但最多不能超过3GB。需要对windows中的启动配置数据(BCD)进行设定,并重启机器。
3、内核模式分区:操作系统代码的驻地。

页交换文件,一般是在磁盘上的虚拟内存,可供任何进程使用。系统中的页交换文件的大小是决定应用程序可用内存总量的最重要因素。
硬盘颠簸:指操作系统把所有的时间都花在页面文件和内存之间交换数据上,导致没有时间运行程序。

Windows提供了三种机制对内存进行操控:
1、虚拟内存:最适合用来管理大型对象数组或大型数据结构
2、内存映射文件:最适合用来管理大型数据流(通常是文件),以及在同一机器上运行的多个进程之间共享数据
3、堆:最适合用来管理大量的小型对象
本文章主要讨论第一种方式。
一、预订地址空间区域
这个操作主要是在一个进程能看到的内存空间上预订地址空间,比如在32位的机器上,一个进程能看到的内存大小是4GB(但其实能供进程用的并没有那么多)。
调用VirtualAlloc函数来预订进程中的地址空间区域。
LPVOID WINAPI VirtualAlloc(
__in LPVOID lpAddress,
__in SIZE_T dwSize,
__in DWORD flAllocationType,
__in DWORD flProtect
);
第一个参数lpAddress是内存地址,用来告诉系统我们想要预订地址空间中的起始地址。如果该参数为NULL,系统会自动找一块闲置区域。但不保证分配方法。
需要注意的是系统始终按照分配粒度(目前在所有Windows平台上都为64KB)的整数倍来分配区域。
如果系统无法满足我们的请求,函数将返回NULL。
第二个参数dwSize用来指定我们想要预订区域的大小,以字节为单位。而系统始终根据CPU页面大小的整数倍来预订区域。在Windows平台下一般是4KB。
第三个参数flAllocationType用来告诉系统用这个函数是要预订区域还是要调拨物理存储企。如果要预订地址空间区域,必须传入MEM_RESERVE参数。
如果希望让系统从尽可能高的内存地址来预订区域,必须传NULL给lpAddress,同时对MEM_TOP_DOWN标志和MEM_RESERVE标志进行按位或操作,并把结果作为flAllocationType传入。
第四个参数flProtect是给区域指定的保护属性。这个属性对于调拨给该区域的物理存储器不起任何作用。因为试图访问区域内的任何内存地址将会引发访问违规。当区域的保护属性和将要调拨的物理存储器的保护属性一致时,系统内部的处理效率会更高。

二、给区域调拨物理存储器
调用的函数还是VirtualAlloc。但第三个参数这次改为MEM_COMMIT。IpAddress和dwSize也会相应改为在物理内存上的操作。

三、同时预订和调拨物理存储器
调用VirtualAlloc,并将第三个参数改为MEM_COMMIT|MEM_RESERVE。