天天看點

《windows核心程式設計》–Windows記憶體體結構(一)

13.1 程序虛拟位址空間

每個程序都有自己的專有位址空間,對32位程序來說,這個位址空間的大小為4GB,這是因為32位指針可以表示從0x00000000-0xffffffff的任意值。對64位程序來說則可以表示0x0000000000000000 到0xffffffffffffffff之間任一值。 因為每一個程序都有自己的專有位址空間,當程序中的各線程運作時,它們隻通路屬于該程序的記憶體。線程即看不到其他程序内容空間,也無法通路它們。 程序A可以在位于它位址空間内的0x12345678位址處存儲一個資料結構,而程序B也可以 “自己的”位址空間存儲一個0x12345678處的記憶體。當程序A通路0x12345678時他通路的是A的資料結構,程序 B通路0x12345678他通路的則是B的這塊資料。程序A中的線程無法通路位于程序 B的位址空間内的資料結構,反之亦然 。 雖然應用程式有這麼大的位址空間可用,但是要記住這隻是虛拟位址空間----不是實體存儲空間。這個位址空間隻不過是一個記憶體位址區間。為了能夠正常讀寫我們還需要把實體存儲器配置設定或映射到相應位址空間,否則将導緻通路違規。

13.2 虛拟位址空間的分區

程序的位址空間是如何劃分的
分區 x86 32位 windows 3GB使用者模式下的x86 32位windows x64 windows ia-64 64位windows 空指針指派分區 0x00000000  0x0000FFFF 0x00000000 00000000  0x00000000 0000FFFF 使用者模式分區 0x00010000  0x7FFFFFFFF 0xBFFFFFFFF 0x00000000 00010000  0x000007FF FFFFFFFF 0x000006FB FFFFFFFF 64 KB 禁入分區 0x7FFF0000  0x7FFFFFFF 0xBFFF0000  0xBFFFFFFF 0x000007FF FFFF0000  0x000006FB FFFF0000  0x000000FB FFFFFFFF 核心模式分區 0x80000000  0xFFFFFFFF 0xc0000000  0x00000800 00000000  0xFFFFFFFF FFFFFFFF 0x000006FC 00000000 

13.2 .1 空指針指派分區

目的:引發違規。 在c++中,錯誤檢查經常不夠徹底,如下代碼 int * pnSomeInteger  = (int * ) malloc(sizeof(int))  *pnSomeInteger = 5; 上面這段代碼malloc如果沒有足夠記憶體,那麼它會傳回NULL,但是前面的代碼漢有檢查這一錯誤。注意:沒有任何辦法可以讓我們配置設定到位于這一位址區間的虛拟位址空間。

13.2 .1 使用者模式分區

這一分區是程序位址空間的駐地。可用的位址敬意和使用者模式分區的大小取決于cpu體系結構 程序無法通過指針來讀取,寫入或以任何方式,通路駐留在這一分區中其它程序的資料。、 CPU體系結構,對應的使用者模式可用位址區間以及大小 cpu體系結構 使用者模式分區的可用位址區間 使用者模式分區的大小 x86(普通) 0x00010000->0x7fffffff ~2GB x86w/3GB 0x00010000->0xBFFFFFFF ~3GB x64 0x000000000001000->0x000007FFFFFFFFFF ~8192GB IA-64 0x00000000 00010000->0x000006FB FFFFFFFF ~7152GB 1. x86 Windows下得到更大的使用者模式分區 2.在64位windows下得到2GB使用者模式分區 3.核心模式分區

13.3 虛拟位址空間的分區

VirtualAlloc配置設定其中的區域(region)。配置設定區域的操作被稱為預訂(reserving)。 當預定時系統會確定區域的起始位址正好是配置設定粒度的整數倍。配置設定粒度會根據不同的CPU平台而有所不同。但是,在寫作本書時所有CPu平台都使用相同的配置設定粒度,大小為64KB,也就是說,系統會把配置設定請求取到64KB的整數倍。 當應用程式預訂位址空間中的一塊區域時,系統會確定區域的大小為正好是系統頁面大小的整數倍。頁面是一個記憶體管理單元,系統通過頁面來管理記憶體。與配置設定粒度相似頁面大小與CPu不同而不同。x86和x64的頁面大小為64KB,而IA-64系統使用的頁面大小為8KB。 說明: 有時候系統會以應用程式的名義來預訂位址空間區域。例如,系統會配置設定一塊位址區間來存放程序環境塊(PEB)。PEB是一個完全由系統建立,操控并銷毀的小型資料結構。 系統同時還需要建立線程環境塊(TEB),系統會線上程建立時配置設定TEB區域,并在銷毀線程時釋放相應區域。

13.4 給區域調撥實體存儲器

為了使用所預訂的位址空間區域,我們還必須配置設定實體存儲器,并将存儲器映射到所預訂的區域。這個過程被稱為調撥(committing)實體存儲器。實體存儲器始終都以頁面為機關來調撥。我們通過調用VirtualAlloc來将實體存儲器給所預訂的區域。 當我們調撥實體存儲器給區域時,并不需要給整個區域都調撥實體存儲器。例如,我們可以預訂一塊大小為64KB的區域,然後把實體存儲器撥給該區域中的第2個頁面和第4個頁面。 當程式不再需要通路所預訂區域中已調撥的實體存儲器時,應該釋放實體存儲器。這個過程被稱為撤銷調撥(decommitting)實體存儲器,通過調用VirtualFree來完成。

13.5 實體存儲器和頁交換檔案

頁交換檔案:硬碟上的檔案一般被稱為頁交換檔案,其中包含虛拟記憶體,可供任何程式使用。
《windows核心程式設計》–Windows記憶體體結構(一)
不在頁交換檔案中維護實體存儲器 在讀過上一節之後,讀者可能會想到,如果許多程式同時運作,頁交換檔案可能會變的相當大----尤其是每次運作一個程式時,系統都必須為該程序的代碼和資料預訂位址空間區域,為這些區域調撥實體存儲器,然後把硬碟上程式檔案中的代碼和資料複制到頁交換檔案中已調撥的實體存儲器中去。事實上,系統并不會執行剛才所說的這些操作。 如使用者要求執行一個應用程式時,系統會打開該應用程式對應.exe檔案并計算出應用程式的代碼和資料的大小,。然後系統會預訂一塊位址空間,并注明與該區域相關靠人為生者實體存儲器就是exe檔案本身。是的,系統燕沒有從頁交換檔案中配置設定空間,而是将exe檔案的實際内容(或檔案映象即file image)用作程式預訂的位址空間區域。這樣一來,不但載入程式非常快,而且頁交換檔案也可以保持一個合理的大小。 當把一個程式位于硬碟上的檔案映象(即一個exe或 dll檔案)用作位址空間區域對應的實體存儲器時,我們稱這個檔案映象為記憶體映射檔案(memory mapped file)。當載入一個exe或dll時,系統會自動預訂空間區域并把檔案映象映射到該區域。但是,系統也提供了一組函數,可以上開發人員把資料檔案映射到位址空間。 當windows從軟碟載入.exe或.dll檔案時,系統會把整個檔案從軟碟複制到記憶體中,此外,系統還會從頁交換檔案中配置設定足夠的存儲空間來存放檔案映象。隻有當系統需要把一個頁面換出記憶體,而頁面又包含檔案映象的一部份時,系統才會寫入頁交換檔案。如果系統的記憶體負載很輕,那麼檔案總是在記憶體中運作。 Microsoft必須讓軟碟上執行的檔案以這種方式 運作,因為隻有這樣安裝程式才能正常運作。通常安裝程式從第一張軟碟開始,在安裝過程中使用者會取出該軟碟并插入其它軟碟。如果系統需要再從第一張軟碟去加載exe或dll的一部分代碼,那麼很顯然,第一張軟碟可能已經不在軟驅中了。但是由于系統已經把檔案複制到了記憶體中(并以頁交換檔案為後備存儲器),是以系統可以随時通路安裝程式而且不會遇到任何問題。 除非映象檔案是用/SWAPRUN:CD或/SWAPRUN:NET開關連結的,否則系統不會把位于其它可移動媒介(比如 CD光牒、或網絡驅動器)上的映象檔案複制到記憶體中的。