?? sy0501.htm
字號:
<html>
<HEAD>
<TITLE>Visual C++與計算機接口</TITLE>
<META HTTP-EQUIV="Content-Type" CONTENT="text/html;charset=gb2312" >
</HEAD>
<body>
<font color="#0000FF">Win32內存管理</font>
<p>
(一)實驗目的:<BR>
學習Win32內存管理<BR><BR>
(二)實驗內容:<BR><BR>
1、進程和內存空間<BR>
Win32中,每個運行的程序就是一個進程,它由兩個部分組成:<BR>
·操作系統用來管理進程的內核對象<BR>
·地址空間<BR>
內核對象也是系統用來存放關于進程的統計信息的地方。地址空間則包含所有可執行模塊或DLL模塊的代碼和數據,它還包含動態內存分配的空間。如線程堆棧和堆分配空間。<BR><BR>
關于進程最重要的是,它擁有自己“私有”的虛擬地址空間。<BR>
對于32位進程來說,這個地址空間是4GB,因為32位指針可以擁有從0x00000000至0xFFFFFFFF之間的任何一個值。這使得一個指針能夠擁有4294967296個值中的一個值,它覆蓋了一個進程的4GB虛擬空間的范圍。<BR>
因此當一個進程正在運行時,該進程只可以訪問屬于它的內存。屬于所有其他進程的內存則隱藏著,并且不能被正在運行的進程訪問。<BR><BR>
2、分頁技術<BR>
注意,虛擬地址空間并不是實際的物理存儲單元,更不是物理內存。<BR>
進程的4GB地址空間一般不會全部使用到,各種代碼和數據被分散到4GB地址空間里,以4KB為邊界,每個單元為4KB大小。<BR>
這樣每個4KB單元稱為一頁,如果一頁被使用了,它就占用了物理存儲單元(但我們并不能看到也不需關心它的物理內存地址)。<BR><BR>
虛擬內存頁有4種狀態:<BR>
·提交頁面:它被分配一個物理存儲單元,在內存中或交換文件中。<BR>
·鎖定頁面:它被強行留在物理內存中,直到解鎖為止。<BR>
·保留頁面:這段地址將被保留,不會再被分配,但它并不被分配一個物理存儲單元。<BR>
·自由頁面<BR><BR>
3、內存異常<BR>
當程序要使用一個未被分配物理存儲單元的頁面時,無論是自由頁面還是保留頁面,就會產生內存異常。<BR>
初學者最常引起內存異常的地方,是當使用一個未分配內存的指針時,還有當訪問內存越界。<BR><BR>
4、VirtualAlloc函數<BR>
在Win32環境下,我們可以使用的內存分配方法有:<BR>
·C:malloc/free<BR>
·C++:new/delete<BR>
·為兼容Win16留下的API:GlobalAlloc/GlobalFree,LocalAlloc/LocalFree<BR>
·堆函數:HeapAlloc/HeapFree<BR>
·虛擬內存函數:VirtualAlloc/VirtualFree<BR>
所有這些方法最終都會調用VirtualAlloc/VirtualFree。<BR><BR>
首先必須知道保留(Reserved)內存和提交(Committed)內存的含義。<BR>
當內存被保留時,一段連續虛擬地址空間被留出,但此時沒有物理RAM被分配。<BR>
當我們實際需要使用這段內存時,我們可以再次調用函數VirtualAlloc來提交被保留的內存空間,此時系統才真正分配物理內存。<BR><BR>
VirtualAlloc的三種常用調用方法,注意size的單位是字節:<BR>
(1)直接申請提交內存:<BR>
int* p = (int*) VirtualAlloc (NULL, size, MEM_COMMIT, PAGE_READWRITE);<BR>
(2)申請保留內存<BR>
int* p = (int*) VirtualAlloc (NULL, size, MEM_RESERVE, PAGE_READWRITE);<BR>
(3)提交保留內存<BR>
VirtualAlloc (p, size, MEM_COMMIT, PAGE_READWRITE);<BR><BR>
VirtualFree的兩種常用調用方法<BR>
(1)將內存由提交內存變為保留內存,這段內存中可以既包括提交頁面也包括保留頁面:<BR>
VirtualFree (p, size, MEM_DECOMMIT);<BR>
(2)釋放內存,這段內存中可以既包括提交頁面也包括保留頁面:<BR>
VirtualFree (p, 0, MEM_RELEASE);<BR>
注意,p必須為VirtualAlloc返回的指針,長度必須填為0,否則出錯。<BR><BR>
5、保留內存與提交內存的一個實例<BR><BR>
假設想實現一個電子表格應用程序,這個電子表格為200行x256列。對于每一個單元格,都需要一個CELLDATA結構來描述單元格的內容。<BR>
要處理這種二維單元格矩陣,最容易的方法是在應用程序中聲明下面的變量:<BR>
CELLDATA CellData[200][256];<BR>
如果CELLDATA結構的大小是128字節,那么這個二維矩陣將需要6553600(200 x 256 x 128)個字節的存儲器。<BR>
如果這些內存都直接用頁文件來分配物理存儲器,那么這是個不小的數目。尤其是考慮到大多數用戶只是將信息放入少數的單元格中,而大部分單元格卻空閑不用,因此顯得有些浪費。內存的利用率非常低。<BR><BR>
傳統上,電子表格一直是用其他數據結構技術來實現的,比如鏈接表等。<BR>
使用鏈接表,只需要為電子表格中實際包含數據的單元格創建CELLDATA結構。由于電子表格中的大多數單元格都是不用的,因此這種方法可以節省大量的內存。<BR>
但是這種方法使得你很難獲得單元格的內容。如果想知道第5行第10列的單元格的內容,必須遍歷鏈接表,才能找到需要的單元格,因此使用鏈接表方法比明確聲明的矩陣方法速度要慢。<BR>
虛擬內存為我們提供了一種兼顧預先聲明二維矩陣和實現鏈接表的兩全其美的方法。<BR>
運用虛擬內存,既可以使用已聲明的矩陣技術進行快速而方便的訪問,又可以利用鏈接表技術大大節省內存的使用量。<BR>
利用虛擬內存技術的優點,程序可以按照下列步驟來編寫:<BR>
(1) 保留一個足夠大的地址空間區域,用來存放CELLDATA結構的整個數組。保留一個根本不使用任何物理存儲器的區域。<BR>
(2) 當用戶將數據輸入一個單元格或對單元格進行其它操作時,找出CELLDATA結構應該進入的保留區域中的內存地址。當然,這時尚未有任何物理存儲器被映射到該地址,因此,訪問該地址的內存的任何企圖都會引發訪問違規。<BR>
(3) 將上一步中找到的內存地址以及所需的地址范圍,提交給系統來分配物理存儲器。這個范圍既可以包含已經提交過的地址,也可以包含沒有提交過的地址。<BR>
(4) 操作單元格,即設置CELLDATA對象屬性。<BR><BR>
現在物理存儲器已經映射到相應的位置,你的程序能夠訪問內存,而不會引發訪問違規。這個虛擬內存技術非常出色,因為只有在用戶將數據輸入電子表格的單元格時,才會提交物理存儲器。由于電子表格中的大多數單元格是空的,因此大部分保留區域沒有提交給它的物理存儲器。<BR>
</p>
</body>
</html>
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -