記憶體對應檔之剖析(一)

來源:互聯網
上載者:User
原文:

記憶體對應檔(Mapping File)是Windows記憶體管理中的重要一環,也是編程

技術中比較進階的一個話題。目前關於這方面的資料比較少,而其實記憶體映射

檔案其實對我們的對於Windows的記憶體瞭解很重要,在這裡把筆者的心得寫

出來,和大家一起討論。

 

                          記憶體空間及映射

    相信大家都已經知道,在WIN32中和16位Windows的最大不同就是WIN32

引入了面向進程的獨立虛擬位址,這個地址的定址空間達到了4GB(2^32),當然

這個地址是虛擬。每個進程擁有自己的獨立空間,進程A的地址0X10000000

和進程B的地址0X10000000沒有絲毫的聯絡(只是在使用者進程地址空間,不包括其他

範圍)。說到這個地方可能大家會奇怪了,我的機器中只有64M(或者128M等)記憶體呀,怎麼會有這麼大的地址空間呢?而進程A和進程B的同樣的地址又會如何識別使得不衝突呢?

   這裡先讓我們來看看Windows的記憶體空間(註:這裡我們都以Win9X來討論,

當然Win2K或者WinNT和9X在某些方面會不大一樣)

                    

                     0x00000000----0x003FFFFF     4M      屬於系統保留地區

 

            0x00400000---0x7FFFFFFF    2G-4M   面向進程獨立的地址空間

 

            0x80000000--0xBFFFFFFF     1G       Win32共用的空間,用來存放

                                                  記憶體對應檔等

         

            0xC0000000---0xFFFFFFFF    1G       用來存放Vxd等

 

有上面的列表可知,使用者的程式運行在第二個位址範圍中,而我們用來討論的對應檔則放在了第三個位址範圍中.而我們偵錯工具的時候經常有看到某個指標變數的值

為多少,這個值就指的是虛擬位址空間中的地址.

    那麼Windows是如何將這個虛擬位址空間轉化為實際的PC上的RAM的地址呢?

這就牽涉到映射的問題,也就是以頁(page)為基本單位實現兩個地址的對應.這個相信

在作業系統這門課裡已經學習過,這裡就不再重複了.在上面這個問題中,地址情況

可能如下:

           進程A                   RAM                    進程B

 

 

 

 

0x10000000

1頁

………

 

1頁          

 

 

 

 

0x10000000

 

 

 

 

 

 

 


這樣,相信大家都已經清楚了程式訪問中的地址空間和具體的OS訪問的地址之間的關係了吧(關於頁的大小,不同的平台有不同的值,Windows的是4K,我們可以用GetSystemInfo這個API返回的SYSTEM_INFO中的dwPageSize得知道)

(備忘2:實際的映射過程中,是以64K為邊界對齊的)

   

虛擬記憶體

然而,我們知道RAM是寶貴而稀少的,早在16位的Windows時代已經推出

了硬碟分頁檔以提供虛擬記憶體,Win32則是提供了硬碟上的分頁檔來繼續

支援虛擬記憶體.根據Richter的說法:”系統頁面的大小是決定應用程式能使用多少

實體記憶體的最重要的因素,RAM只是很小的影響”.在實際的記憶體訪問過程中,系統

先會上RAM中尋找需要的資料,如果找不到,就會提供一個分頁錯誤讓OS上頁面

檔案上去找,如果找到則把分頁檔的內容載入到RAM繼續訪問,否則就報錯

提示”無效的分頁錯誤”(也是我們最常碰到的程式錯誤).在這裡,我們不妨把頁面

檔案理解為”後備的RAM”.(Windows提供給使用者控制虛擬記憶體的方法是在

控制台中的系統選項).所以在這種情況下,RAM的主要作用只是起到了

和硬碟上的分頁檔做資料的交換,所以才有了Richter的說法.

      如果使用者程式要自己使用虛擬記憶體,那麼首先的第一步是在進程地址

空間中保留(rerserve)一塊地址(在4M—2G中),然後再把這塊空間提交(commit)

給真正的記憶體.Windows提供給我們的對虛擬記憶體的操作介面是VirtualAlloc和

VirtualFree這一組API,這樣我們就可以利用虛擬記憶體的龐大的特性來處理

一般程式難以解決的問題.比如假設有個二維結構Item[300][256];裡面每個單位

為200個位元組, 現在要修改裡面的某個單元,要實際的分配這麼大的記憶體幾乎是

不可能的,而分匹處理又難以體現二維結構直接用下標訪問的簡潔性,這樣我們

就可以先保留下這個龐大的結構,然後只提交要修改的部分給實際的記憶體,使得

最後的操作簡潔而有效.

Windows提供的保留和提交虛擬記憶體的函數只是一個:VirtualAlloc,不過是裡面

的參數不一樣,拿上面的例子而言,我們可以這樣處理:

 

LPVOID pStart = NULL;      

LPVOID pItem = NULL;

DWORD Offset=0;

 // 在系統預設位置保留整個資料結構,返回保留的首地址 

pStart =VirtualAlloc(NULL,300*256*200, MEM_RESERVE,PAGE_READWRITE);

 …

 // 計算出要存取的位移位置

 ….

// 只提交其中的一部分給記憶體

pItem =VirtualAlloc(pStart+Offset,200,MEM_RESERVE,PAGE_READWRITE);

 // 直接修改

pItem=….  

VirtualFree(pStart, 300*256*200, PAGE_READWRITE); 

 

     可是虛擬記憶體也會帶來不方便的地方,假設我們要運行一個程式,按照前面

的做法是要使用到分頁檔來作為虛擬記憶體而訪問,這樣系統必然是先保留

程式的地址空間,然後提交實體記憶體,接下來把資料和代碼從硬碟上的程式檔案

拷貝到系統的分頁檔,最後載入運行.這樣的結果必然是使得載入一個應用

程式的時間變的很長,所以系統真正的做法是把程式檔案(.exe)直接當作是記憶體

檔案而使用,這樣就不再從分頁檔中分配空間使得載入的時間大大增加.

     這個特性無疑是非常誘人的,居然可以直接拿檔案當記憶體,那不是很方便嗎?

是的.在系統載入exe檔案和dll檔案的時候,系統是自動這麼處理的.那麼如果

是一般的資料檔案要使用這種特性可以嗎?答案是肯定的,也就是我們繞了一個

大圈子最終要說的今天的話題:記憶體對應檔.

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.