VC++技術內幕(第四版)筆記(第9章)

第九章:Win32內存管理


1,一個程序就是一個EXE文件。Windows中,一旦一個程序被啓動的,系統爲其創建一個進程。一個進程擁有自己的內存,文件句柄,和其它的系統資源。如果連續兩次啓動同一個程序,系統爲其創建兩個獨立的進程併發運行(併發:微觀交替串行,宏觀並行)。
說明:
1)一個進程(如Windows Wxplorer)可能有多個主窗口(每一個窗口由一個線程支持),也可能沒有任何窗口。
2)進程擁有自己“私有”4GB虛擬地址空間。
3)每個進程內存空間包含各種各樣的內容(具體參見169頁): 程序EXE鏡像,程序中裝入的非系統的DLL(包括MFC DLL),程序的全局數據,程序的堆棧,動態分配內存(包括Windows和C運行庫堆),內存映射文件,進程之間共享的內存塊,特定執行線程的局部內存,所有系統內存模塊(包括虛擬內存表),Windows核心、執行過程及DLL(是OS的一部分)。


2,Windows 95進程地址空間:
WIN95中,只有底下的2GB(0-0x7FFFFFFF)地址空間是進程私有的。其中最底下的4MB禁止訪問。堆棧、堆和可讀寫的全局內存,及其應用程序的EXE和DLL文件都被映射底下的2GB地址上。
上面的2GB地址空間對所有的進程都一樣的,由所有的進程共享。
WIN95核心、執行過程、虛擬設備驅動程序和文件系統代碼,以及一些重要的表(如:頁表),都被映射到最上面的1GB(0xC0000000-0xFFFFFFFF)地址空間。
Windows DLL和內存映射文件位於0x80000000-0xBFFFFFFF地址空間。
安全性說明:
1)所有的EXE和DLL代碼都有隻讀標記,因而可以映射到幾個不同的進程中。
2)一個進程不可能改寫另一個進程私有的2GB地址空間內容。
3)進程地址空間中最上面的2GB由於是共享的,很容易受攻擊毀壞。如:錯誤進程毀壞這一區域重要的系統表,進程的內存映射文件被其它進程弄亂。

3,Windows NT進程地址空間:
WIN NT中,進程只能訪問它最底下的2GB地址空間(除最底和最高的64K是不能訪問)即:0x00010000-0x7FFEFFFF。
EXE、應用程序的DLL 和 Windows的DLL、以及內存映射文件都駐留在0x00010000-0x7FFEFFFF地址空間中。
Windows NT內核、可執行程序和設備驅動程序都被映射到上面的2GB空間中,完全受保護,可以避免錯誤程序的侵入。
安全性分析:
1)進程內存地址空間上2GB空間,完全受保護,可以避免錯誤程序的侵入破壞其中內容。
2)內存映射文件更安全,如果不知道文件的名字,而又沒有顯式地映射視圖,一個進程不能訪問另一個進程的內存映射文件。

4,實際中RAM一般沒有GB級別,Windows是使用虛擬鏡像技術的(通過內存與磁盤的頁置換完成的)。

5,程序中如果需要動態內存,可使用Win32函數VirtualAlloc和VirtualFree函數,也可以直接使用Windows 堆函數(如:HeapAlloc 和 HeapFree)和CRT函數(C運行庫堆函數,如malloc,new,free,delete)來完成任務。

6,堆是特定進程的內存池。當程序需要內存塊的時候,調用堆內存分配函數,並在使用完時調用相關的堆內存釋放函數釋放內存。
Windows 堆函數(如:HeapAlloc 和 HeapFree)和CRT函數(C運行庫堆函數,如malloc,new,free,delete).
C++代碼中,new,delete函數直接映射到malloc,free函數。
說明:
new,delete函數與malloc,free函數比較優點:new,delete函數進行類型檢查,自動計算要分配類型的大小,而且屬於C++語言的一部分。malloc,free函數是作爲標準庫函數提供給C的,它們並不是C語言的一部分。

7, 內存映射文件:
處理如在程序中讀如DIB(設備無關位圖文件)的問題時候:文件小一般是分配一個大小合適的緩衝區,打開文件,然後把整個文件讀入緩衝區;如果文件大則可使內存映射文件來處理。
內存映射文件是:直接映射一個地址範圍到相應的文件(注:個人理解 文件仍然存放在存放在磁盤上),當進程訪問該範圍內存頁時候,OS分配RAM並從磁盤中讀入該頁數據。
說明:
1)默認情況下,當映射文件時候,雖然可能只映射文件的一部分,但整個文件仍然被佔用。
2)MFC裏不支持內存映射文件。CSshareFile類只支持HGLOBAL句柄進行剪切板內存傳輸,不大實用。

8,資源包含在EXE和DLL裏,因此會佔用虛擬地址空間,而且這些空間在進程的生存期內不會被改變。這就使我們很容易直接讀取一個資源(如用LoadResource函數加載位圖資源)
說明:
LoadResource : loads the specified resource into global memory.
HGLOBAL LoadResource(
  HMODULE hModule, // resource-module handle
  HRSRC hResInfo   // resource handle
);
LoadResource返回一個HGLOBAL值,但可以安全把它當成指針來使用(強制轉換)。

9,堆使用的越多,程序的運行效率就越底下。WIN32程序的堆可以很大(要多大就有多大,沒有64KB限制,WIN16有16K的限制)。
                                                                                                                              
////////////////
//////////////
說明:由於缺乏這方面的編程經驗,書中翻譯的這部分內容有比較拗口難懂,筆記裏刪漏好多的內容,建議看看原著。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章