您當前的位置:首頁 > 攝影

Windows記憶體管理分析(四)

作者:由 看雪 發表于 攝影時間:2018-03-23

七、頁面的換出

前文看到,當申請記憶體時發現物理記憶體已經快不足時就會觸發事件,讓平衡執行緒去換出一些頁面到磁碟中,保證物理頁面還足夠。這個平衡執行緒執行的函式為MiBalancerThread

Windows記憶體管理分析(四)

這個執行緒處於不斷的等待之中,如果時間一到或者申請記憶體物理頁面已經過低時,KeWaitForMultipleObjects就會等待到資源繼續執行

Windows記憶體管理分析(四)

如果是2級分頁的話,每次遍歷一個大頁面,判斷一下每個物理頁面的引用計數,如果已經為0並且頁面又是有效的那就會回收這個物理頁面

Windows記憶體管理分析(四)

接下來判斷遍歷系統每種型別的消費者,呼叫它們的修剪函式來修剪記憶體,此時如果消費者們都不肯騰出空間,那麼視為嚴重錯誤,我們分析MiTrimMemoryConsumer函式

Windows記憶體管理分析(四)

引數1是消費者型別,引數2是要釋放的頁面數量,首先判斷消費者是否提供了Trim函式,如果沒有直接返回原來的數值,如果頁面使用數量大於頁面原有的配給量,證明消費者過度使用,相減表明可以騰出多少空間,如果這時候還小於系統最小可用頁數,那就必須把目標消減頁數設定成剛好可以等於系統最小可用頁數

Windows記憶體管理分析(四)

Windows記憶體管理分析(四)

迴圈的呼叫每個消費者的修剪函式。實際上OS只提供了1種消費者MmTrimUserMemory的函式,系統消費者和快取消費者都不提供。事實上,分頁記憶體池的Trim函式還沒有實現,否則在平衡執行緒中,也應該加入分頁記憶體池的trim函式。

Windows記憶體管理分析(四)

這個使用LRU演算法 迴圈知道修剪了目標引數給定的頁數

Windows記憶體管理分析(四)

在物理頁面分配和回收的時候我們已經見過這個點陣圖MiUserPfnBitMap

然後呼叫MmPageOutPhysicalAddress換出到磁碟中

在此之前介紹一個PFN的一個型別為PMM_RMAP_ENTRY的 RmapListHead成員

Windows記憶體管理分析(四)

MM_RMAP_ENTRY是一個單向連結串列,它組織起來這個物理頁面目前正在被誰所對映。對Process的解釋卻有2種,一種就是單純的程序結構體,另一種是Section快取頁表,下文進行解釋

首先我們來看一下怎麼把一個物理頁面倒換,使用的函式是MmPageOutPhysicalAddress

Windows記憶體管理分析(四)

首先獲取PFN資料庫具體MMPFN項,然後獲取這個連結串列頭,開始遍歷,然後獲取對應的程序與頁面基地址

Windows記憶體管理分析(四)

頁面基地址必須是4KB對齊,否則是嚴重錯誤

接下來判斷地址是否處於使用者空間,如果是則獲取程序結構體對應的Vm成員,獲取對整個虛擬空間的描述,否則是核心就獲取核心的。

Windows記憶體管理分析(四)

加鎖之後,獲取這個地址所在的MM_AREA,如果為空,或者這個AREA已經被刪除,返回錯誤。

Windows記憶體管理分析(四)

如果是一個SECTION,計算這個地址在SECTION的偏移,然後取出對應的頁表項,交由MmPageOutSectionView做真正的處理

Windows記憶體管理分析(四)

如果是快取型別就呼叫MmpPageOutPhysicalAddress做真正處理

我們來分析這2個函式MmPageOutSectionView,MmpPageOutPhysicalAddress

Windows記憶體管理分析(四)

首先是透過物理頁號呼叫MmGetSectionAssociation獲取對應的區和檔案偏移,具體怎麼透過物理頁號獲得這2個資訊呢。

Windows記憶體管理分析(四)

Windows記憶體管理分析(四)

Windows記憶體管理分析(四)

我們之前學過MMPFN有一個型別為MM_RMAP_ENTRY的成員連線著所有對映這個物理頁面的一個連結串列,這個函式建立起這種聯絡過程,提供物理頁號,程序,地址就可以構建MM_RMAP_ENTRY並插入,但是在設定這種聯絡的時候如果給定的地址 高24位全1的話此時的EPROCESS實際上是型別為CACHE_SECTION_PAGE_TABLE的頁表指標

Windows記憶體管理分析(四)

所以只要這個AREA是SECTION_VIEW型別,那麼給定頁號,就可以知道它對映到哪些物理頁面(透過RmapListHead成員),不僅如此,還可以知道它對映在程序的哪個虛擬地址(RmapListHead結構成員的Address),如果這個虛擬地址同樣也是屬於SECTION的話 那麼就可以獲取到CACHE_SECTION_PAGE_TABLE,裡面的成員Segment就是我們想要獲得的區,還有具體的檔案偏移。

接下來程式碼進行檢查後,來到

Windows記憶體管理分析(四)

Windows記憶體管理分析(四)

進入迴圈遍歷這些對映的頁面,首先過濾掉Address是段對映的那些內容。這時候判斷這個頁面是使用者還是系統,使用者的話獲取使用者的MMSUPPORT,系統獲取系統的MMSUPPORT

Windows記憶體管理分析(四)

Windows記憶體管理分析(四)

接下來定位到這個虛擬地址定位到程序具體的AREA,透過呼叫

MmPageOutCacheSection將這個AREA的內容全部換出磁碟。

Windows記憶體管理分析(四)

先介紹SwapEntry, MMPFN結構體有一個SwapEntry,表明這個物理頁面當前正在交換檔案具體位置。我們看程式碼怎麼樣從一個頁表項轉換成一個SwapEntry

Windows記憶體管理分析(四)

實際上就是頁表項右移1位。SwapEntry如果是MM_WAIT_ENTRY 代表它正在被人處理中

Windows記憶體管理分析(四)

頁表中,如果一個頁面被換出,那麼頁表中存著的是一個SSE。我們來看SSE是什麼

Windows記憶體管理分析(四)

實際上就是物理頁號左移頁面偏移位數(預設12位)。

Windows記憶體管理分析(四)

第1個位元位記錄著它是否是一個交換檔案

Windows記憶體管理分析(四)

並且第2個位元位記錄是否是髒的SSE

判斷一個頁表項是交換檔案

Windows記憶體管理分析(四)

可知是 PA_PRESENT位為0,並且0x800的位元位為1時(這個位元位ia32並沒有進行使用)

Windows記憶體管理分析(四)

回到程式碼中,這個函式判斷這個頁表項是否正在被他人處理中,如果是就返回SUCCESS+1讓他人等待,如果不是解除了對應物理頁面MMPFN項的RmapListHead中關於引數給定MMSUPPORT(可定位到程序)的對映,然後再取消該程序對於此頁面的對映(將有效位置位0),緊接著MmReleasePageMemoryConsumer遞減引用計數,如果引用計數變為0就會釋放這個物理頁面掛入空閒連結串列。這樣的話就完成了這個程序頁面取消對映,然後程式碼基本上就是迴圈遍歷,不再講述。我們回到MmpPageOutPhysicalAddress的程式碼。

如果返回值是SUCCESS+1,代表剛才的倒換項已經被他人在處理。直接返回失敗

如果正常的話迴圈執行MmPageOutCacheSection後就已經將所有關於對映到此物理頁面的AREA全部取消對映。然後進入

Windows記憶體管理分析(四)

如果有SEGMENT的存著,呼叫MmFinalizeSectionPageOut將Section換出,換出後設置SEGMENT的頁表為對應的SSE。我們分析這個函式MmFinalizeSectionPageOut

Windows記憶體管理分析(四)

取出這個物理頁號對應的交換項

Windows記憶體管理分析(四)

這裡判斷了是否是髒頁面,如果是髒頁面,為了保持磁碟和記憶體資料一致,我們要將其寫回磁碟

Windows記憶體管理分析(四)

寫回磁碟的函式先對這個頁面做臨時的對映,因為這裡是Section的換出,首先是根據檔案物件,和檔案當前的偏移然後呼叫IO函式寫到磁碟,這裡是檔案管理的內容,我們不做分析。

這樣就完成了寫入磁碟。

Windows記憶體管理分析(四)

透過MAKE_SWAP_SSE 把一個SWAP轉換成一個SSE(實際上就是左移1位),因為如果是頁面檔案,寫入頁表的不應該是SWAPENTRY,而是SSE。

如果成功就應該把物理頁號對應的MMPFN項的swapentry設定成0,因為它等下就要被釋放了,它現在是全新的,如果還是原來的值的話,這個頁面被申請的時候,可能就和原有頁面檔案起衝突。

遞減SEGMENT的引用計數之後判斷SEGMENT的引用計數是否為0,是的話呼叫MmFinalizeSegment,結束這個Segment的生命。我們來學習怎麼結束一個SEGMENT的生命週期

Windows記憶體管理分析(四)

將本SECTION_SEGMENT從連結串列中刪除,接下來如果這個是一個DATA_SEGMENT,就將SEGEMENT的檔案物件進行相關設定,透過呼叫

Windows記憶體管理分析(四)

呼叫引數FreePage將頁表內所有的頁面釋放 引數FreePage的值是MiFreeSegmentPage,代表每次釋放一個頁

Windows記憶體管理分析(四)

根據FileOffset下標來獲取對應的entry (SSE),如果當前頁面並沒有對應倒換檔案,繼續判斷是不是一個髒的SSE,如果是就要寫回頁面檔案。然後設定這個頁表項為0,遞減該物理記憶體頁PFN引用計數。如果頁面對應了倒換檔案呼叫

MmFreeSwapPage將這個倒換頁面釋放

Windows記憶體管理分析(四)

Windows記憶體管理分析(四)

從宏定義的認識我麼也可以看到低4位定位出PagingFileList的下標,高21位(32-11)定位出AllocMap的具體位置。我們來分析一下頁面檔案是怎麼實現的。

Windows記憶體管理分析(四)

這個結構體代表一個頁面檔案,PagingFileListEntry把所有頁面檔案串聯在一起,FileObject表示具體的檔案物件,MaximumSize代表這個頁面檔案最大支援多少位元組,CurrentSize代表當前用了多少位元組,FreePages為還可以使用多少頁,UsedPage為當前使用了多少頁,AllocMap為陣列,是檔案的內容。

Windows記憶體管理分析(四)

PagingFileList 是PAGINGFILE指標陣列 一個16個元素

Windows記憶體管理分析(四)

申請頁面檔案就會從這個陣列中進行申請。釋放和申請都比較簡單,就不再討論

這裡程式碼深入學習的層次比較多,我們跳回最上面一層,MmPageOutPhysicalAddress對SECTION_VIEW情況的處理,上面討論的情況是AREA_CACHE的情況。

Windows記憶體管理分析(四)

呼叫MmSetPageEntrySectionSegme將對應頁表項的內容設定成MM_WAIT_ENTRY<<1,表明這一項已經被正在被換出,然後呼叫MmPageOutSectionView進行實際上的換出操作。

Windows記憶體管理分析(四)

是頁面換出上下文,在這裡面填好資訊方便進行使用,填完上下文資訊後,呼叫

Windows記憶體管理分析(四)

刪除所有物理頁面相關對映,呼叫MmPageOutDeleteMapping將頁面換出

Windows記憶體管理分析(四)

總結來說,對一個物理頁面的換出過程,首先是尋找到對這個頁面所有對映的程序,對這個地址進行一一的取消對映,當取消對映完畢後,會判斷這個頁面是否為髒頁面,如果是髒頁面就寫回磁碟,然後將這個物理頁面掛入空閒連結串列(透過引用計數),完成了物理頁面的釋放。

[原創]Windows記憶體管理分析-『程式設計技術』-看雪安全論壇

weixin。qq。com/r/M3W7oxbE-0uArVLA9yAh (二維碼自動識別)

標簽: 頁面  物理  頁表  對映  這個