=============================================================
標題:Windows CE虛擬內存
備註:
日期:2011.3.12
姓名:朱銘雷
=============================================================
一 獲取系統內存信息:
MEMORYSTATUS memstatus;
memstatus.dwLength = sizeof(MEMORYSTATUS);
GlobalMemoryStatus(&memstatus);
結果:
dwMemoryLoad字段表示當前內存使用率爲34%,但這個數字不精確。
dwTotalPhys字段表示當前的程序內存總計爲52104KB(53354496個byte)。
dwAvailPhys字段表示當前可用的程序內存還剩34736(KB)(35569664個byte)。
dwTotalVirtual字段表示當前程序可以使用的虛擬地址空間總量爲32M,可用的還剩27.8M。
我測試的系統是Windows CE 5.0,系統中最多可以有32個進程,每個進程可以使用的虛擬地址空間爲32M。這種情況在Windows CE 6.0中得到了很大改善,最大進程數貌似是32K個,每個進程可以使用的虛擬地址空間爲2G。
Windows CE 5.0的進程虛擬地址空間分配圖:
Windows CE 6.0的進程虛擬地址空間分配圖:
二 虛擬內存
1 VirtualAlloc 分配虛擬內存
const int PAGESIZE = 4096;
LPVOID pMem1 = 0, pMem2 = 0;
pMem1 = VirtualAlloc(NULL, PAGESIZE, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
pMem2 = VirtualAlloc(NULL, PAGESIZE, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
這段代碼的本意是想分配兩個單頁(4K字節)大小的虛擬內存,第一個參數設置爲NULL,由系統來決定在何處分配內存。訪問權限是可讀可寫。
但實際調試時發現,每次提交一個頁面大小的虛擬內存時,實際上分配的是0x10000(64K字節)大小的虛擬內存,原因是進行了64KB字節的邊界對齊,這就造成了虛擬內存空間的嚴重浪費。理想一點的解決方法是,首先“保留”(MEM_RESERVE)一塊64KB(或其整數倍)字節大小的虛擬內存,然後在需要的時候提交該區域的一個頁面或幾個頁面。
const int PAGESIZE = 4096;
LPVOID pMemBase = 0, pMem1 = 0, pMem2 = 0;
pMemBase = VirtualAlloc(NULL, PAGESIZE*16, MEM_RESERVE, PAGE_NOACCESS);
pMem1 = VirtualAlloc(pMemBase, PAGESIZE, MEM_COMMIT, PAGE_READWRITE);
pMem2 = VirtualAlloc((PBYTE)pMemBase+PAGESIZE, PAGESIZE, MEM_COMMIT, PAGE_READWRITE);
調試時,可以看出pMem1所指的虛擬內存,實際分配了0x1000(4K字節)大小的虛擬內存。
2 VirtualFree回收釋放虛擬內存
回收是使頁面處於“保留”狀態,取消虛擬內存到物理內存之間的映射。上面那段代碼申請了64KB大小的虛擬內存,其中8KB(兩頁)處於“提交”狀態,剩餘處於“保留”狀態。這時先回收已“提交”部分,再整體“釋放”。如果區域中既有“提交”頁面,又有“保留”頁面,則VirtualFree將失敗。
VirtualFree(pMem1, PAGESIZE, MEM_DECOMMIT);
VirtualFree(pMem2, PAGESIZE, MEM_DECOMMIT);
VirtualFree(pMemBase, 0, MEM_RELEASE);
3 VirtualProtect改變訪問權限
VirtualProtect只能改變已“提交”頁面的訪問權限。
DWORD dwOldProtect = 0;
VirtualProtect(pMem1, PAGESIZE, PAGE_READONLY, &dwOldProtect);
4 VirtualQuery查詢訪問權限
MEMORY_BASIC_INFORMATION memInfo;
VirtualQuery(pMemBase, &memInfo, sizeof(MEMORY_BASIC_INFORMATION));
BaseAddress是傳遞給VirtualQuery函數準備查詢權限的頁地址,AllocationBase是VirtualAlloc分配虛擬內存時的初始地址,AllocationProtect爲1(PAGE_NOACCESS),說明該區域最初分配時訪問權限爲PAGE_NOACCESS,RegionSize包含從BaseAddress地址開始,具有相同屬性的頁的字節大小,這裏爲0x1000(4KB)字節大小,實際上就是pMem1所指的區域大小,其屬性PAGE_READONLY(經過上面更改)與pMem2所指的區域PAGE_READWRITE不同。State爲0x1000(MEM_COMMIT)表明該區域中的頁面處於“提交”狀態。Protect爲0x02(PAGE_READONLY),是該區域當前的訪問權限。Type爲0x20000(MEM_PRIVATE),表明該區域爲當前進程私有。