Windows內存管理分析(二)

Windows內存管理分析(二)

二、物理內存的管理

內核管理的最小單位是頁面,首先來看物理頁面的表示 MMPFN描述了一個物理頁面所需要的信息

Windows內存管理分析(二)

Windows內存管理分析(二)

NextStackPfn指向一個棧的物理頁面,這個字段用於要刪除或者增加內核棧的空間的時候用於指向下一個物理頁面、PteAddress指向MMPTE結構,代表一個頁表項

MMPFN的u3.e1是一個MMPFN_ENTRY結構

Windows內存管理分析(二)

描述這個頁面內核一些數據結構需要的字段,例如PageColor是代表這個頁面的顏色,至於其他一些成員等見到再進行討論。PfnUsage代表這個物理頁面的用途,類型是一個枚舉值

MmPfnDatabase是由MMPFN組成的數組,稱為PFN數據庫,通過物理頁面的編號來確定數組的下標,比如0號頁面對應數組的0號元素,Flink和Blink可以被插入到一個鏈表中,那為什麼已經有數據庫將每一個物理頁的信息都存儲了,還要用鏈表串在一起呢?這是因為系統維護了幾個鏈表做特定功能使用,這些鏈表用到的成員就是Flink和Blink。

MMPTE_HARDWARE跟體系相關,x86定義如下,可看出跟IA-32的PTE/PDE是一致的

Windows內存管理分析(二)

Windows內存管理分析(二)

MMPTE用來表示頁表項PTE,但是它也可以用作PDE或者PPE,PXE,如果MMPTE包含一個有效的地址,那麼就使用hard字段執行MMPTE_HARDWARE,MMU可以用它來完成地址的轉換。上面說到,系統維護了幾個鏈表來做特定用途,鏈表的定義是

Windows內存管理分析(二)

成員Flink和Blink就是上文提到PFN的兩個成員,MMLISTS是枚舉值,代表這個鏈表的類型

系統維護的分別是

Windows內存管理分析(二)

就緒(Standby)、已修改(Modified)、無寫修改(ModifiedNoWrite),空閒(Free),只讀(Rom),損壞(Bad),零化(Zeroed)

並且加入了MmPageLocationList數組之中,可以在數組中利用鏈表枚舉類型MMLISTS來進行方便的定位。如下所示

Windows內存管理分析(二)

上文提到的MMPFN_ENTRY結構體的成員PageLocation就代表物理頁具體存儲在這個數組的哪個元素

Windows內存管理分析(二)

MMCOLOR_TABLES記錄了一個鏈表,可以用來組織已經著色的頁面

有了上述結構體的大概認識,我們來結合具體函數分析這些結構體的使用。分配物理內存使用MmAllocPage函數

Windows內存管理分析(二)

參數為要申請的內存類型,然後返回一個物理頁面編號。獲取PFN的自旋鎖後,從零化頁面找出一個物理頁號(並在原零化鏈表中移除),然後根據這個頁號在PFN數據庫中獲取具體的PFN結構體信息,進行初始化各項成員,引用計數設置為1。這樣就完成了一個物理頁面的申請。我們來分析MiRemoveZeroPage的實現,分析如何申請一個0化的頁面。分段閱讀

Windows內存管理分析(二)

MmFreePagesByColor是一個PMMCOLOR_TABLES數組,也就是一個二維數組,定義如下

Windows內存管理分析(二)

MmSecondaryColors和下面出現的MmSecondaryColorMask是輔助顏色值和輔助掩碼,MmSecondaryColors我個人理解為當前可用最大的顏色值。

FreePageList是一個上文提到的MMLIST枚舉值,轉換為整數是1,所以數組有2個元素,訪問時通過枚舉值進行訪問。這個數組第一個元素是零化的著色頁面,第二個元素是空閒著色的頁面。數組的二維是一個由COLOR顏色值作下標的數組,通過COLOR值就可以獲取到對應顏色的頁面鏈表,該鏈表的所有顏色就是這個COLOR。我們可以看到從0化頁面的對應顏色值取出了一個鏈表。

Windows內存管理分析(二)

接下來判斷鏈表的頭個元素的值是否是LIST_HEAD,LIST_HEAD是宏定義為-1,也就是這個鏈表中如果沒有值的話就要用-1表示。如果對應顏色的物理頁面鏈表為空,沒有元素的話,就應該從系統維護的零化頁面鏈表中取出一個新頁面,這裡通過PageIndex&MmSecondaryColorMask計算出新的COLOR值,可以看出COLOR值實際上是通過物理頁面下標來進行確定的。如果系統維護的零化頁面鏈表也為空,更新一下Zero值,表明等一下取出來的頁面應該手動去零化,然後從系統空閒頁面鏈表MmFreePageListHead取出頁面,同樣更新COLOR值,這時候如果MmFreePageListHead也為空,我們可以看到暫未實現。

Windows內存管理分析(二)

根據頁面下標來取出PFN數據庫對應的PFN項目,進行檢查,如果需要零化就進行零化處理。我們分析MiRemovePageByColor的實現,分段閱讀

Windows內存管理分析(二)

首先從頁面下標獲取對應MMPFN項,然後通過該項的MMPFN_ENTRY獲取得到頁面當前所處的系統維護的鏈表,這是通過PageLocation來獲得的,獲取到鏈表頭後,進行Total的減1,代表鏈表中元素個數減一

Windows內存管理分析(二)

然後就是數據結構相關內容,從系統維護的鏈表中刪除該結點。

Windows內存管理分析(二)

接下來取出MmFreePagesByColor對應的元素,也相應的將其刪除。更新計數。

我們還看到使用了MiDecrementAvailablePages函數,這個函數主要是遞減全局變量MmAvailablePages,如果過低就判斷為系統可用內存過低觸發事件來修剪。

通過SouceInsight查看MmAllocPage的函數為MmRequestPageMemoryConsumer,它實現了一個更通用的,可以為特定請求進行申請內存。

Windows內存管理分析(二)

Consumer為宏定義

Cache代表緩存用,USER是用戶用,SYSTEM是系統使用,MAXIUM當前共有幾種用途,就是這3種用途

再看一個結構體

Windows內存管理分析(二)

表明一個特定用途的消費者。系統將消費者分類存入了一個數組

Windows內存管理分析(二)

表明一共3種消費者

Windows內存管理分析(二)

首先增加該消費者類型對應數組的頁面使用數量,如果頁面數量使用次數過多,並且當前線程不是平衡用的線程,就要修剪騰出一些物理頁面

Windows內存管理分析(二)

用MmAllocPage申請一個頁面返回 如果是用戶進行申請頁面MmInsertLRULastUserPage 設置用戶PFN位圖MiUserPfnBitMap,但是實際上在此處是用戶申請這個應該永遠不成立。前面已經過濾了只剩下系統的消費者了。

Windows內存管理分析(二)

Windows內存管理分析(二)

如果系統可用頁數已經小於最小可用頁數,那麼判斷調用者是否可用等待,如果不能等待,直接返回沒有內存錯誤,如果可以等待,就等待平衡線程去修剪內存騰出物理頁面,如果這時候還沒有頁碼,那麼就是嚴重錯誤了。這裡我們可以看到系統消費者和其他消費者的一個區別,如果系統消費者需要內存,就申請一個物理頁面,然後調用平衡線程去強制修剪其他的,但是如果是非系統消費者,如果不想等待就直接返回沒有內存,如果要等待就必須要等其他物理內存騰出,才能輪得到它申請到。

Windows內存管理分析(二)

接下來是最後的申請頁面操作,前面有判斷的條件都不成立時,最終就執行到這裡。

接下來分析頁面釋放函數

Windows內存管理分析(二)

Windows內存管理分析(二)

函數很短,首先是判斷引用計數是否為1,如果是1代表是這個頁面目前只被引用一次,可以被掛入空閒鏈表

在這個函數中遞減了頁面引用計數,然後如果為0就會被掛入空閒鏈表之中。

讓我們再看一下這個函數

Windows內存管理分析(二)

這個函數一般是這個頁面又被引用的時候進行使用,至此我們可以看到一個物理頁面的生命週期,首先是被申請,引用計數為1,接下來可能會被繼續引用(例如2個不同的虛擬地址頁面實際上指向一個物理頁面),當引用計數為0的時候,就會被掛入空閒鏈表MmFreePageListHead之中,並且也同樣掛入物理頁面對應的顏色鏈表MmFreePagesByColor中

更多幹貨等著你~

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


分享到:


相關文章: