1. 程式人生 > >windows虛擬內存機制

windows虛擬內存機制

copy tar 高峰 產生 指定 roc use 數據 內存地址

在windows系統中個,每個進程擁有自己獨立的虛擬地址空間(Virtual Address Space)。這一地址空間的大小與計算機硬件、操作系統以及應用程序都有關系。

對於32位程序來說,最多能使用2GB空間(0x00010000-0x7FFEFFFF)。為了獲得3GB的地址空間,在不同的windows系統中可以按照如下方法來進行擴充。

1.操作系統方面

① 32位windowsXP

技術分享

② 32位win7 -- 管理員權限執行命令:bcdedit /set increaseuserva 3072來開啟

③ 64位win7 -- 對32位程序默認開啟3GB,無需額外設置

2.應用程序方面

無論是32位還是64位windows若要讓32位程序能使用3GB內存,必須在鏈接時加上參數: /LARGEADDRESSAWARE

進程地址空間區段

技術分享

註:進程地址空間在低地址,操作系統內核在高地址

進程地址空間分布(以2GB為例)

技術分享

Windows系統在進程空間中專門劃出一塊0x70000000 - 0x80000000(共256MB)區域,用於映射這些常用的系統DLL(如kernel32.dll、ntdll.dll等)

對系統DLL的默認基地址進行調整,防止加載時沖突,觸發ReBasing(重定基地址)

註:基地址必須對齊到分配粒度(64KB)

Win7下,exe在PE文件中基地址為0x400000,DllPrj.dll的基地址為0x10000000且該地址未被其他dll占用;但實際exe被映射到0xEC0000,DllPrj.dll被映射到0x535A0000

生成exe和dll模塊時,鏈接時使用了參數/DYNAMICBASE(啟用動態基地址)

註:地址空間布局隨機化, Address space layout randomization (ASLR):防範惡意程序對已知地址進行攻擊

windows內存分配過程可細化為以下3個要點:

① 保留一段虛擬內存地址空間:從進程的4GB中保留一段地址空間。// 帶MEM_RESERVE參數的VirtualAlloc函數

起始地址必須是系統分配粒度的整數倍(64KB),大小必須是系統頁面大小的整數倍(4KB)。

② 提交一段虛擬內存地址空間:將進程已保留的一段地址空間映射機器的虛擬內存上。// 帶MEM_COMMIT參數的VirtualAlloc函數

起始地址和大小都必須是頁面大小的整數倍(4KB)。

③ 將虛擬內存地址空間映射到物理內存頁(RAM):在訪問進程提交的頁面被訪問時,通過缺頁中斷(又名頁缺失、頁面錯誤, PageFault)機制來真正分配物理內存頁,同時修改對應頁面的地址空間映射關系。

註1:在程序中所訪問的地址都必須是保留並提交的虛擬內存地址

註2:可以使用VirtualFree來釋放保留或提交的虛擬內存地址空間

內存指標概念

技術分享

技術分享

虛擬內存:

Private Bytes // 進程Committed的虛擬內存字節數 對應win7任務管理器中的【提交大小】,資源管理器中的【提交】

Peak Private Bytes // 進程Committed的虛擬內存的最高峰字節數

Virtual Size // 進程Reserved的虛擬地址空間字節數

Page Faults // 發生過的缺頁中斷次數 對應win7任務管理器中的【頁面錯誤】

物理內存:

Working Set = WS Private + WS Shareable // 進程占用物理內存總字節數 對應win7任務管理器中的【工作設置(內存)】,資源管理器中的【工作集】

WS Private // 進程獨享的物理內存字節數(如:堆內存+棧內存+cow機制創建的內存) 對應win7任務管理器中的【內存(專用工作集)】,資源管理器中的【專用】

WS Shareable // 進程可與其他進程共享的物理內存字節數(如:exe及dll代碼段、數據段等) 對應win7資源管理器中的【可共享】

WS Shared // 進程已與其他進程共享的物理內存字節數,WS Shared<=WS Shareable

// 若只啟動一個exe實例,那麽exe的代碼段、數據段等不會被共享,因而就不統計在WS Shared中

Peak Working Set // 物理內存的最高峰字節數 對應win7任務管理器中的【峰值工作設置(內存)】

註:無論是虛擬內存還是物理內存下的各個指標,都是通過統計用戶態的那部分占用

頁交換文件

頁交換文件(Page File):一般被用作可寫物理內存頁的後備存儲器。Windows下該文件名為pagefile.sys,位於各盤的根目錄中。

可以根據機器的軟硬件狀況來設置頁交換文件的大小,甚至關閉頁交換文件的使用。

技術分享

技術分享

頁出(Page Out):當物理內存不夠時,系統會將一些不經常使用且有後備的物理內存頁釋放,並將虛擬地址映射關系指向後備。

①以頁交換文件(如:堆、棧等)為後備:在頁交換文件中分配空間,並拷貝內容到其中後再釋放

②以內存映射文件(如:exe、dll等)為後備:直接釋放

頁入(Page In):當系統讀取某個虛擬內存地址,而該地址所在的頁不在物理內存頁中時,將產生一個缺頁中斷,

告訴系統從頁交換文件或者內存映射文件中取回包含該地址的虛擬內存頁(即:將內容拷回到物理內存頁,並建立新的虛擬地址映射到物理內存頁上,然後釋放頁交換文件中對應部分的空間) 。

寫時復制機制

寫時復制機制(copy on write, COW):當WRITECOPY屬性內存頁面被修改時,會觸發內存頁拷貝,以此來節省物理內存和頁交換文件的占用。

註:系統在映射exe或dll文件時會把數據頁指定為PAGE_WRITECOPY屬性,代碼頁指定為PAGE_EXECUTE_WRITECOPY屬性

具體過程:

① 當進程對內存頁執行修改操作時,系統會找一個閑置的物理內存頁,並拷貝所有內容到新頁上,然後標記新頁的後備存儲器為頁交換文件,最後將進程的虛擬內存頁指向新的物理內存頁。

② 經過上述步驟,進程就可以使用自己副本了,修改在新的物理頁上進行,而不對原來的內存頁產生任何影響。

重定基地址

重定基地址(Rebasing):模塊裝載時,如果目標地址被占用或基於安全考慮,系統會根據模塊的所需地址空間的大小為其分配一個新的基地址,並將模塊裝載到該基地址處。

問題:

① 一旦發生了Rebasing,當模塊映射時,要對重定位表中所有頁進行地址修正。

② 系統修正這些地址的頁面時,會觸發寫時復制機制。

地址空間布局隨機化(Address space layout randomization,ASLR)

微軟在Vista系統中引入了名為ASLR的技術,模塊每次會被加載到隨機位置(偽隨機),防範惡意程序對已知地址進行攻擊。

ASLR不僅對模塊地址做了隨機處理,還對堆、棧、進程環境塊(Process Environment Block, PEB)、線程環境塊(Thread Environment Block, TEB)的地址也進行了隨機化。

ASLR技術將Rebasing放到內核中進行處理,意味著可以在系統範圍上(原來只能在進程範圍內),最大程度上減少Rebasing的發生,從而節省物理內存和頁交換文件的使用。

PE文件裝載

技術分享

註:映射必須以頁面(4KB)為單位,並按照頁邊界進行對齊

執行完映射後,絕大部分指令和數據都還沒有被裝入物理內存中。裝載過程是隨著程序的執行動態進行的。

具體過程:cpu在訪問指令和數據時,發現該地址所在的頁不在物理內存頁中時,會觸發缺頁中斷,此時系統會找一個閑置的物理內存頁,並將內容從後備中(映像文件或頁交換文件中)載入到該物理內存頁中。

windows虛擬內存機制