Memory Management(內存管理)
GlobalMemoryStatus
此函數用於獲得系統當前物理內存和虛擬內存的使用情況。
函數聲明如下:
參數表:
返回值:
無返回值
說明:
您可以使用該函數來判斷當前您可以在系統中分配到多少不會與其它程序相沖突的內存。
這個函數的返回是不確定的,無法保證連續兩次調用該函數會得到相同的返回信息。
在一臺內存超過4GB的機器上,GlobalMemoryStatus 函數會返回錯誤值。Windows2000或之後的版本會報告一個 -1 的值來表示數據溢出。之前的版本如windosNT則報告一個對真實內存取4GB模的一個值。由於以上的原因,我們使用GlobalMemoryStatusEx 取代該函數。
在一臺擁有大於2GB而小於4GB內存的intel x86機器上GlobalMemoryStatus 函數總是在結構MEMORYSTATUS 成員dwTotalPhys 中返回2GB。同樣的,如果總的可用內存在2 - 4GB之間,結構MEMORYSTATUS 的成員dwAvailPhys 最大可能值爲2GB。如果可執行文件在連接時使用”/LARGEADDRESSWARE ”連接開關,那麼函數GlobalMemoryStatus 會在以上兩個成員中返回正確的值。
Virtual Address Space(虛擬地址空間)
虛擬地址表示的是進程中非實際物理地址的位置。換句話說就是,系統爲每個進程維護着一個頁面映射,這個頁面映射是一個內部的數據結構,它的作用是將虛擬地址轉換爲相應的物理地址。
虛擬地址空間分爲以下幾部分:
Windows NT 4.0 SP3 Server Enterprise Edition, Windows 2000 Advanced Server, and Windows .NET Enterprise Server:一般的,進程能夠使用低端的3GB空間(0x00000000 到 0xBFFFFFFF)。高端的1GB內存(0xC0000000 到 0xFFFFFFFF)爲系統保留部分。
Windows NT/2000/XP: 進程能夠使用低端的2GB內存(0x00000000 到 0x7FFFFFFF),高端的2GB內存(0x80000000 到 0xFFFFFFFF)系統保留。
Windows 95/98/Me: 對應描述如下表
區間
|
用途
|
0K - ~64K (0xFFFF)
|
不可寫。這塊區域大約應是爲系統裝載一些MS-DOS的特性而保留的。這塊內存對於進程而言是私有的。
|
~64K (0x10000) - 4 MB (0x3FFFFF)
|
爲兼容MS-DOS保留。這塊內存對進程而言可讀可寫。然而,這段區域有可能保存着一些MS-DOS相關的結構或代碼,所以進程不應該在這段區域隨意讀出或寫入。這塊內存對於進程而言是私有的。
|
4MB (0x400000) - 2GB (0x7FFFFFFF)
|
用於代碼和用戶數據。用戶數據可讀可寫。代碼是隻執行的。這塊內存對進程而言是私有的。
|
2GB (0x80000000) - 3GB (0xBFFFFFFF)
|
共享區。對於所有進程都可讀寫。一些系統的動態連接庫和其它一些數據裝載到這段區域。
|
3GB (0xC0000000) - 4GB (0xFFFFFFFF)
|
系統內存。對任意進程都是可讀可寫。然而,需要注意的是,這段內存是保存低等級的系統代碼的地方,所以,向這片區域寫入數據可能會破壞系統可能造成災難性後果。.
|
詳情請參閱MSDN
下期預告:
Virtual Memory Functions(虛擬內存函數族)
此族函數用於進程操作或決定虛擬內存地址空間中頁面的狀態。他們可以實現以下一些操作:
1、 預留一個虛擬地址空間的區域。預留的地址空間不佔用任何的實際物理內存,但是會防止其它分配操作在此範圍內分配內存。它不會影響其它進程的虛擬地址空間。當進程需要把一個動態增長的數據結構分配在一個預留的內存空間中時,預留內存操作避免不必要的物理內存佔用。進程在需要時能夠爲這塊空間分配物理內存。
2、 將進程虛擬地址空間預留頁的範圍提交給進程,這樣,這片物理存儲區(不論是內存還是磁盤)只能被此進程訪問。
3、 描述已提交頁面區域的讀/寫、只讀、拒絕訪問等屬性。不同於標準的分配函數的地方是它分配的頁面總有 讀/寫 屬性。
4、 釋放已預留的內存區域。使這片虛擬內存區域對於調用進程後來的分配操作處於可用狀態。
5、 把已提交頁面區域解除提交。釋放對應的物理存儲區,使之對於後來的任意進程的分配操作有效。
6、 鎖定一頁或更多已提交頁到物理內存中,使這些被鎖定頁面不回被系統交換到頁面文件中。
7、 獲得關於調用進程或指定進程虛擬地址空間某一區域之內已提交頁面的資料。
8、 改變調用進程或指定進程虛擬地址空間指定區域已提交頁面的訪問限制級。
更多詳細資料,請看下回分解
下期預告:
Memory Management Functions (內存管理函數)
Allocating Virtual Memory (分配虛擬內存)
虛擬內存函數用於操作內存頁面。這些函數用當前機器上的頁面的大小來實現描述內存的大小和地址的功能。
VirtualAlloc 函數執行以下的操作中的一個:
1、 預留一頁或多頁的自由頁面。
2、 提交一頁或多頁預留頁面。
3、 預留和提交一頁或多頁自由頁面。
你可以指定你要預留或提交頁面的起始地址,或者你也可以讓系統來決定這個地址。函數將指定的地址調整到適當的頁面邊界。預留頁面是不允許訪問的,但已提交的頁面可以被以頁讀/寫、頁只讀、頁訪問禁止等訪問規則進行分配。當頁面被提交之後,在頁面文件中就分配了存儲區,但所有頁面都只是在第一次試圖讀或寫該頁面的時候被調入物理內存。你可以用一般指針來訪問用VirtualAlloc函數提交的內存。
Freeing Virtual Memory (釋放虛擬內存)
VirtualFree函數執行以下操作中的一個:
1、 取消提交一個或更多的已提交頁面,把頁面狀態切換到預留。取消提交的頁面將釋放於該頁面相關聯的物理存儲區,使這片區域能夠被任意進程重新使用。所有被提交的頁面塊都可以被取消提交。
2、 釋放一片包含一個或多個預留頁面的內存塊,把頁面狀態切換到空閒。已釋放的頁面塊能夠被該進程重新使用。被預留頁面只能夠一次釋放全部的之前使用VirtualAlloc函數預留的塊。
3、 同時取消提交和釋放一個包含一個或多個頁面的塊,將這些頁面的狀態切換爲空閒。指定的塊必須包含全部之前使用VirtualAlloc函數預留的塊,而且通常所有這些頁面已經被提交。
當一個內存塊被釋放或者取消提交之後,你就不能再引用它。所有之前在其中的信息都永遠消失。試圖在一個空閒頁面上執行讀寫操作會導致一個訪問違例。如果你還需要這些某些信息,那麼請不要取消提交或者釋放包含這些資料的內存。
如果想要說明某片內存區域的數據不再游泳,那麼在調用VirtualAlloc時使用MEM_RESET參數。這樣這些頁面上的數據將不會在讀取或寫入頁面文件。然而,這塊內存仍可再次被使用。
Working With Pages (頁面操作)
使用GetSystemInfo函數能夠得到當前機器的頁面大小。
VirtualQuery 和VirtualQuerayEx函數能夠返回關於 某一進程的地址空間中始於指定地址的連續的頁面空間 的資料。VirtualQuery返回關於調用進程的內存資料。VirtualQueryEx返回關於指定進程的內存資料而且通常能夠支持需要處於調試態進程資料的調試器。頁面區域會被限制在 向下調整到最近頁面邊界的指定地址上。一直延伸到所有擁有以下共同特性的後續頁面:
1、 所有頁面狀態一致:是已提交或預留或空閒三狀態之一。
2、 如果起始頁面非空閒,那麼所有該區域頁面都是被VirtualAlloc一起初始化的內存頁面組的一部分。
3、 所有頁面訪問控制級都一致:是 頁只讀、頁讀寫、頁禁止訪問三級之一。
VirtualLock函數使進程能夠鎖定一頁或多頁已提交內存進入物理內存(RAM),防止系統將這些頁面交換到頁面文件中。它能夠被用於確保在不進行磁盤訪問的情況下使臨界數據可訪問。鎖定頁面進內存是危險的,這是因爲它會限制系統管理內存的能力。的使用VirtualLock函數能夠導致可執行代碼被交換到頁面文件從而降低系統性能。VirtualUnlock函數將被VirtualLock鎖定的內存解鎖。
VirtualProtect函數能夠調整所有在進程地址空間中的已提交頁面的訪問限制級。比如,進程可以分配讀寫頁面來存儲常變數據,並且之後它能夠把訪問控制級改變爲只讀或者禁止訪問來防止以外的改寫。VirtualProtect是一個用VirtualAlloc分配的頁面上的典型的應用,但是,它也能夠應用於使用其它分配函數分配的頁面上。然而,VirtualProtect改變了全部頁面的保護級,但是其它分配函數返回的指針並不一定要頁面對齊。VirtualProtectEx函數類似於VirtualProtect函數,除了它只改變指定進程內存的限制級之外。改變限制級在調試器訪問被調試進程的內存的時候會很有用處。
Memory Management Functions (內存管理函數)
以下的函數用於內存管理
函數
|
描述
|
|
將一塊內存從位置拷貝到另外一個位置
|
|
將指定內存塊內容填充爲指定數據
|
|
查找已經被寫入虛擬內存區域的頁面地址
|
|
獲得關於系統當前對於物理內存和虛擬的內存的使用信息。
|
|
獲得關於系統當前對於物理內存和虛擬的內存的使用信息。
|
|
決定調用進程是否擁有對指定地址內存的讀操作權。
|
|
檢驗調用進程是否擁有對指定內存範圍的讀操作權。
|
|
檢驗調用進程是否擁有對指定字符串所在地址區域的讀操作權。
|
|
檢驗調用進程是否擁有對指定內存範圍的寫操作權。
|
|
將一塊內存從一個位置移動到另外的位置。
|
|
爲某片虛擬內存區域重置寫跟蹤狀態。
|
|
用零值填充某片內存塊。
|
以下是 AWE(Address Windowing Extensions) 函數
函數
|
描述
|
|
分配物理內存頁面與進程的AWE區域建立或取消映射
|
|
釋放先前由AllocateUserPhysicalPages函數分配的物理內存頁面。
|
|
映射在AWE區域內的指定地址分配的物理內存。
|
|
同上
|
以下的函數是全局(global)和本地(local)函數。這類函數運行速度較之其它內存管理函數爲慢並且有很多特性沒有提供。這就是說,新的應用程序應該儘量使用堆函數(heap functions).然而,全局函數(global functions)仍然被用在DDE和剪貼板操作中。
函數
|
描述
|
|
從堆中分配指定字節數量的內存。
|
|
丟棄指定的全局內存塊
|
|
返回關於指定全局內存對象的信息
|
|
釋放指定的全局內存對象。
|
|
返回指定全局內存塊的指針的句柄。
|
|
鎖定一個全局內存對象並且返回指向該內存塊第一個字節的指針。
|
|
改變指定全局內存對象的大小和屬性。
|
|
得到指定內存對象的當前大小。
|
|
減少對一個內存對象的鎖定數量。
|
|
從堆中分配指定數量的內存。
|
|
丟棄指定的本地內存對象
|
|
返回關於指定本地內存對象的信息。
|
|
釋放指定的本地內存對象。
|
|
得到指向指定本地內存對象的指針的句柄。
|
|
鎖定本地內存對象並且返回指向該內存對象的第一個字節的指針。
|
|
改變指定本地內存對象的大小或者屬性。
|
|
返回指定本地內存對象的當前大小。
|
|
減少對某內存對象的鎖定數量。
|
以下是堆函數族。
函數
|
描述
|
|
獲得調用進程的堆的一個句柄。
|
|
獲得調用進程所有有效的堆的句柄。
|
|
從堆中分配一塊內存
|
|
嘗試壓緊指定的堆。
|
|
創建一個堆對象。
|
|
銷燬指定的堆對象。
|
|
釋放一塊從堆中分配的內存。
|
|
嘗試獲得與指定堆關聯的鎖定。
|
|
獲得關於指定堆的資料。
|
|
從堆中重新分配一塊內存。
|
|
爲指定的堆設置堆信息。
|
|
獲得一個在堆上的內存塊的大小。
|
|
獲得與指定堆相關聯的一個鎖定的所有者。
|
|
嘗試使指定的堆有效。
|
|
枚舉指定堆上的內存塊。
|
以下是虛擬內存函數。
函數
|
描述
|
|
保留或提交調用進程虛擬地址空間的某一區域的頁面。
|
|
保留或提交調用進程虛擬地址空間的某一區域的頁面。
|
|
釋放或取消提交調用進程虛擬地址空間的某一區域的頁面。
|
|
釋放或取消提交調用進程虛擬地址空間的某一區域的頁面。
|
|
鎖定指定的進程虛擬地址空間的指定塊到物理內存中。
|
|
改變調用進程虛擬地址空間已提交頁面區域的訪問限制級。
|
|
改變調用進程虛擬地址空間已提交頁面區域的訪問限制級。
|
|
提供關於調用進程虛擬地址空間頁面區域的資料。
|
|
提供關於調用進程虛擬地址空間頁面區域的資料。
|
|
對某進程虛擬地址空間的某區域的頁面解鎖。
|