進程的虛擬地址空間
對于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。