在windows系統中個,每個進程擁有自己獨立的虛擬地址空間(Virtual Address Space)。這一地址空間的大小與電腦硬體、操作系統以及應用程式都有關係。 對於32位程式來說,最多能使用2GB空間(0x00010000-0x7FFEFFFF)。為了獲得3GB的地址空間,在不同的win ...
在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在訪問指令和數據時,發現該地址所在的頁不在物理記憶體頁中時,會觸發缺頁中斷,此時系統會找一個閑置的物理記憶體頁,並將內容從後備中(映像文件或頁交換文件中)載入到該物理記憶體頁中。