Top Banner
Team 7 吳吳吳 吳吳吳吳 吳吳吳 、、 吳吳吳 吳吳吳吳 吳吳吳 、、 吳吳吳 吳吳吳吳 吳吳吳 、、 吳吳吳 吳吳吳吳 吳吳吳 、、 odern Operating System Kernels Presentati Topic: Windows Memory Management Department of Computer Science & Information Engineering, National Central University
166

Team 7

Jan 03, 2016

Download

Documents

anika-valencia

Modern Operating System Kernels Presentation. Topic: Windows Memory Management. Team 7. 吳藺剛、陳嘉浩、余修丞 吳彥諄、吳政樺、黃詩蘋 劉乃菀、黃柏軒、姜智文 卓卿安、洪國勛、郭星辰. Department of Computer Science & Information Engineering, National Central University. Outline. 4.6 工作集管理 4.6.1 Windows 工作集管理員 4.6.2 平衡集管理員 - PowerPoint PPT Presentation
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
Page 1: Team 7

Team

7吳藺剛、陳嘉浩、余修丞吳彥諄、吳政樺、黃詩蘋劉乃菀、黃柏軒、姜智文卓卿安、洪國勛、郭星辰

Modern Operating System Kernels PresentationTopic: Windows Memory Management

Department of Computer Science & Information Engineering, National Central University

Page 2: Team 7

4.4 記憶體分頁 4.4.3 分頁錯誤處理 4.4.4 Windows 的寫時複製

4.5 實體記憶體管理 4.5.1 PFN 資料庫 4.5.2 實體頁面的狀態變化 4.5.3 實體頁面串列的管理和操作 4.5.4 修改頁面寫出器 4.5.5 行程 / 堆疊交換器 4.5.6 低 / 高記憶體通知

Outline

4.6 工作集管理 4.6.1 Windows 工作集管理員 4.6.2 平衡集管理員

4.7 記憶體監視工具 4.7.1 記憶體監監視工 4.4.4 Windows 的寫時複製

4.8 本章總結

Page 3: Team 7

4.4.3 分頁錯誤處理2012/6/13

陳嘉浩

Page 4: Team 7

回顧Intel x86 中的 PDE 和 PTE

無效 PTE 和原型 PTE

分頁錯誤處理分頁錯誤的類型錯誤檢查的流程錯誤處理的方法

Outline

Page 5: Team 7

Intel x86 的 PDE 和 PTE

5

PDE: Page Directory

Entry

PTE: Page Table Entry

註解

Page 6: Team 7

無效 PTE 情形

6

分頁檔轉移 0 0 保護 PFN* 0

31 015 410 912 11

轉移位元

原型位元

位於分頁檔

分頁框架編號(PFN) 1 0 保護 0

31 01510 912 11

轉移位元

原型位元

WU/SCd Wt

234

頁面正在轉移

0 0 0 保護 0 0

31 015 410 912 11

要求一個零頁面

0 0

031 1

未知原因錯誤

PFN: Page Frame Number

稍候在 4.5 章將會介紹

註解

Page 7: Team 7

原型 PTE 介紹

7

指向原型 PTE 的無效 PTE

Page 8: Team 7

原型 PTE 例子行程 A 分頁目錄

行程 B 分頁目錄

行程 B 分頁表

行程 A 分頁表

記憶體集區的區段物件

分頁檔

實體記憶體

無效

修改自第六組投影片

8

Page 9: Team 7

行程 A 分頁目錄

行程 B 分頁目錄

行程 B 分頁表

行程 A 分頁表

記憶體集區的區段物件

分頁檔

實體記憶體

有效無效

假設行程 A 要存取頁面 P2 ,它會發現分頁表中 P2 的 PTE 是無效的,但它會指向原型 PTE ,而原型 PTE 此時也是無效的且指向分頁檔中的頁面,此時記憶體管理員會根據原型 PTE 的指示為 P2 分配一個實體頁面

實體頁面分配完成後,行程 A 分頁表中的 PTE 以及原型 PTE 都會指向該實體分頁,此時行程 A 分頁表中的 PTE 以及原型 PTE 都為有效,而行程 B 分頁表中的 PTE 則保持原狀

當行程 B 要存取頁面 P2 時,它依然會發現自己的 PTE 是無效的,因此它會檢查原型 PTE ,並且發現 P2 已經在實體記憶體中了。接著P2 分頁表中的 PTE 則會重新指向到實體頁面

Page 10: Team 7

分頁錯誤種類 無效 PTE

• 頁面位於分頁檔或對應檔案中• 存取一個尚在記憶體中但正在轉移過程中的頁面• 存取一個尚未提交的頁面• 存取一個要求零的頁面

在使用者模式下存取只能在核心的頁面

寫一個唯讀的頁面

寫一個防護的頁面

執行標記為「不可執行」頁面中的程式碼

寫一個標記為「寫時複製」頁面10

解決辦法

將該頁面轉移回到行程工作集或系統工作集

回傳值STATUS_SUCCESS

STATUS_PAGE_FAULT_TRANSITIO

NSTATUS_IN_PAGE_ERROR

解決辦法

申請一個填滿零的頁面,並加入到目前行程的工作集

回傳值STATUS_SUCCESS

STATUS_PAGE_FAULT_DEMAND_ZER

O

STATUS_IN_PAGE_ERROR

解決辦法

分配一個實體頁面並且從硬碟上讀入內容

回傳值STATUS_SUCCESS

STATUS_PAGE_FAULT_PAGING_FIL

E

STATUS_IN_PAGE_ERROR

解決辦法

複製目前行程私有的頁面,並替換原來的頁面

回傳值STATUS_SUCCESS

STATUS_PAGE_FAULT_COPY_ON_WRIT

E

STATUS_IN_PAGE_ERROR回傳值

STATUS_ACCESS_VIOLATIO

N

回傳值

STATUS_PAGE_FAULT_GUARD_PAG

E

Page 11: Team 7

分頁錯誤檢查流程 – MmAccessFault() 函式

11

APC: Asynchronous Procedure

Call ,屬於 IRQL 中斷層級,用於實現延遲和異步的過程調用。詳細請參考第 5.2.2 節

註解

Page 12: Team 7

分頁錯誤檢查流程 – 系統位址空間

12

分頁檔轉移 0 0 保護 PFN* 0

31 015 410 912 11

轉移位元

原型位元

位於分頁檔

分頁框架編號(PFN) 1 0 保護 0

31 01510 912 11

轉移位元

原型位元

WU/SCd Wt

234

頁面正在轉移

0 0

031 1

未知原因錯誤

Page 13: Team 7

分頁錯誤檢查流程 – 使用者位址空間13

Page 14: Team 7

分頁錯誤處理方法 – MiDispatchFault() 函式

14

原型 PTE

檢查如果原型 PTE 表示了頁面尚在記憶體中,即原型 PTE 是有效的,或在轉移狀態,則可以先將原型 PTE 變成有效,然後設置實際的 PTE

否則,呼叫 MiResolveProtoPteFault() 函式根據情況進行處理,然後呼叫 MiCompleteProtoPteFault() 函式把已經有效的原型 PTE 影響到真正的 PTE

正在轉移的 PTE

要求零頁面的 PTE

在分頁檔中的 PTE

Page 15: Team 7

分頁錯誤處理方法 – MiDispatchFault() 函式

15

原型 PTE

正在轉移的 PTE

呼叫 MiResolveTransitionFault() 函式,把正在轉移的頁面從它所在的串列中移除,並重新設置 PTE ,使它變成一個有效的 PTE

要求零頁面的 PTE

在分頁檔中的 PTE

Page 16: Team 7

分頁錯誤處理方法 – MiDispatchFault() 函式

16

原型 PTE

正在轉移的 PTE

要求零頁面的 PTE

呼叫 MiResolveDemandZeroFault() 函式向系統要一個記憶體頁面,然後設置好 PFN 資料庫中對應該頁面的項目,以及出錯虛擬位址的硬體 PTE

在分頁檔中的 PTE

Page 17: Team 7

分頁錯誤處理方法 – MiDispatchFault() 函式

17

原型 PTE

正在轉移的 PTE

要求零頁面的 PTE

在分頁檔中的 PTE

呼叫 MiResolvePageFileFault() 函式將出錯頁面的 PTE 設置為正在轉移以及讀取操作正在進行。該函式不會發起 I/O ,而只是填充好這些資訊,放在輸出參數的 ReadBlock 中

WHY?

Page 18: Team 7

分頁錯誤處理方法 – MiDispatchFault() 函式

18

各種錯誤的輔助處理函式最後都會回傳結果訊息給 MiDispatchFault() 函式作後續處理,它會根據回傳的指示決定是否需要呼叫IoPageRead() 函式發出 I/O請求,並且針對I/O 成功與否作相關的處理。最後, MiDispatchFault() 也會負責釋放資源以及維護鎖的一致性

Page 19: Team 7

小結

19

在本章節裡面,我們探討了:有哪些可能導致分頁錯誤的情形MmAccessFault() 函式如何透過剖析 PDE

和 PTE 判斷分頁錯誤屬於哪一種情形MiDispatchFault() 函式如何針對各種分頁錯

誤情形進行處理

Page 20: Team 7

20

2012/6/13

郭星辰姜智文

4.4.4 Windows 的寫時複製

Page 21: Team 7

21

現代作業系統的一個重要特性

機制1. 父行程、子行程為獨立的分頁表,但分頁表指向相同

的實體頁面(唯讀)2. 當行程寫數據,記憶體管理員複製頁面,父行程、子

行程擁有私有頁面(可讀寫)

Windows 的寫時複製 (copy-on-write)

Page 22: Team 7

22

將複製的動作延遲到真正需要兩個行程分配各自私有頁面的時候,避免不必要的資料複製,減緩了對記憶體的需求

寫時複製的優點

Page 23: Team 7

23

記憶體區段物件創建函數 NtCreateSection 和MmCreateSection 參數 SectionPageProtection指定了記憶體區段物件中頁面的保護屬性PAGE_READ ( 讀 )PAGE_READWRITE ( 完全共用,只有一個 )PAGE_WRITECOPY ( 寫時複製 )

實作原理

Page 24: Team 7

24

建立記憶體區段物件

NtCreateSection

MmCreateSection

MiSectionInitialization 建立實體記憶體區物件

分頁檔支撐的記憶體集區MiCreatePagingFileM

ap

映像檔記憶體集區MiCreateImageFileM

ap

資料檔案記憶體集區MiCreateDataFileMap

保護屬性由MmCreateSection 參數SectionPageProtection 經MiMakeProtectionMask 函式變化而來, PAGE_WRITECOPY 變為MM_WRITECOPY此函式建立的映像檔記憶體區預設情形皆為寫時複製的,除非SECTION 有特別設定不相容的保護屬性

頁面保護屬性為MM_EXECUTE_READWRITE ,可讀寫、可執行、不可寫時複製

Page 25: Team 7

25

PTE 資料結構MMPTE_HARDWARE 中,第 9 位元是一個保留位元, Windows 將他解釋成CopyOnWrite 位元

PTE 分頁表項目

Page 26: Team 7

26

階段一: 一個寫時複製的頁面被第一次分配第一次存取頁面時,硬體 PTE 無效MiCompleteProtoPteFault 呼叫巨集來 填充 PTE 的

位元定義中,寫時複製保護屬性為 0x200 ,即 PTE 中的第

9 位元 設置為 1 ,而寫位元 (第 1 位元 ) 設置 0 ,發生分頁錯誤

實作過程 (1/2)

Page 27: Team 7

27

階段二:一個行程對一個支援寫時複製的頁面執行了寫入操作,觸發一個分頁錯誤MmAccessFault 檢測錯誤 → 呼叫 MiCopyOnWrite

實作過程 (2/2)

1. 根據參數中指定的出錯位址找到 PFN 資料庫中對應的項,印證他是一個原型 PTE2. 透過 MiRemoveAnyPage申請一個實體頁面3. 呼叫 MiInitializeCopyOnWritePfn初始化其 PFN 對應的項4. 從系統 PTE 區域中申請一個空閒 PTE ,完成記憶體頁面的複製5. 填好出錯位址 PTE 項目6. 舊頁面 PFN 資料庫中計數減一

Page 28: Team 7

28

4.5 實體記憶體管理

Page 29: Team 7

29

2012/6/13

黃詩蘋姜智文

4.5.1 PFN 資料庫

Page 30: Team 7

30

PFN 資料庫union { MMPTE OriginalPte; LONG AweReferenceCount; } ;union { ULONG_PTR EntireFrame; struct { ULONG_PTR PteFrame: 25; ULONG_PTR InPageError : 1; ULONG_PTR VerifierAllocation : 1; ULONG_PTR AweAllocation : 1; ULONG_PTR Priority : MI_PFN_PRIORITY_BITS;

ULONG_PTR MustBeCached : 1; };} u4;} MMPFN, *PMMPFN;

Extern PMMPFN MmPfnDatabase;

# define (index) (&MmPfnDatabase[index])

MI_PFN_ELEMENT

typedef struct _MMPFN { union { PFN_NUMBER Flink; WSLE_NUMBER WsIndex; PKEVENT Event; NTSTATUS ReadStatus; SINGLE_LIST_ENTRY NextStackPfn; } u1; PMMPTE PteAddress; union { PFN_NUMBER Blink; ULONG_PTR ShareCount; } u2; union { struct { USHORT ReferenceCount; MMPFNENTRY e1; } ; struct { USHORT ReferenceCount; USHORT ShortFlags; } e2; } u3;

Page 31: Team 7

31

實體頁面的可能狀態 (1/2)1.活動狀態 (active) •頁面正在被某個行程使用,或者被用

於系統空間 (非分頁集區,或者在系 統工作集 )•有效的 PTE 指向頁面

2.備用狀態 (standby) •原屬於某個行程或系統,但現在已從 工作集中移除•頁面的內容尚未被修改•原 PTE 正在轉移的無效 PTE

3. 已修改狀態 (modified)

•頁面的內容已被修改過•原 PTE 正在轉移的無效 PTE

4. 已修改但不寫出 (modified no-write)

•類似於 3. ,但差別在於,記憶體管理 員不會將內容寫到磁碟上

Page 32: Team 7

32

實體頁面的可能狀態 (2/2)

5. 轉移狀態•頁面正進行 I/O 操作•若發生分頁錯誤時,可透過此狀態判斷出衝突 的情形

6. 空閒狀態 •頁面是空閒的,不屬於任何一個工作集

7. 零化狀態 •內容歸零,也不屬於任何一個工作集

8. 壞狀態 •產生硬體錯誤

Page 33: Team 7

33

請問實體頁面的狀態有哪些呢 ? 請列出五種來吧ˊ _>ˋ

~問題來囉~

Page 34: Team 7

34

(a)活動狀態頁面的 PFN項目

union { WSLE_NUMBER WsIndex; } u1; PMMPTE PteAddress; union { ULONG_PTR ShareCount; } u2; union { struct { USHORT ReferenceCount; MMPFNENTRY e1; } ; } u3;MMPTE OriginalPte;union { struct { ULONG_PTR PteFrame: 25; ULONG_PTR InPageError : 1; ULONG_PTR VerifierAllocation : 1; ULONG_PTR AweAllocation : 1; ULONG_PTR Priority : 3; ULONG_PTR MustBeCached : 1; };} u4;

union { PFN_NUMBER Flink; } u1; PMMPTE PteAddress; union { PFN_NUMBER Blink; } u2; union { struct { USHORT ReferenceCount; MMPFNENTRY e1; } ; } u3;MMPTE OriginalPte;union { struct { ULONG_PTR PteFrame: 25; ULONG_PTR InPageError : 1; ULONG_PTR VerifierAllocation : 1; ULONG_PTR AweAllocation : 1; ULONG_PTR Priority : 3; ULONG_PTR MustBeCached : 1; };} u4;

(b)備用狀態或已修改狀態的 PFN項目(c)歸零的或空閒頁面的 PFN項目

union { PKEVENT Event; NTSTATUS ReadStatus; } u1; PMMPTE PteAddress; union { ULONG_PTR ShareCount; } u2; union { struct { USHORT ReferenceCount; MMPFNENTRY e1; } ; } u3;MMPTE OriginalPte;union { struct { ULONG_PTR PteFrame: 25; ULONG_PTR InPageError : 1; ULONG_PTR VerifierAllocation : 1; ULONG_PTR AweAllocation : 1; ULONG_PTR Priority : 3; ULONG_PTR MustBeCached : 1; };} u4;

(d)轉移狀態的 PFN項目

MMPFN 資料結構

Page 35: Team 7

35

typedef struct _MMPFNENTRY { USHORT Modified : 1 ; USHORT ReadInProgress : 1 ; USHORT WriteInProgress : 1 ; USHORT PrototypePte : 1 ; USHORT PageColor : 4 ; USHORT PageLocation : 3 ; USHORT RemovalRequested :

1 ; USHORT CacheAttribute : 2 USHORT Rom : 1 ; USHORT ParityError : 1 ;} MMPFNENTRY ;

MMPFNENTRY 定義頁面已被修改

原型 PTE

正進行”讀取”或”寫入”操作

頁面狀態

Page 36: Team 7

36

PFN 資料庫和實體頁面串列

Page 37: Team 7

37

2012/6/13

余修丞姜智文

4.5.2 實體頁面的狀態變化

Page 38: Team 7

38

記憶體管理員根據「系統記憶體的數量」以及各個「行程對於記憶體的需求」,動態調度實體頁面的使用

ex: 當一行程需要記憶體,記憶體管理員可以從「零化串列」或「空閒串列」中找到頁面滿足行程需求

行程結束,記憶體管理員回收行程的頁面

頁面的調度與使用

Page 39: Team 7

39

記憶體管理員動態調度的過程,頁面可能會經歷各種變化

實體頁面的狀態轉移

工作集( 行程或系

統 )

歸零串列 空閒串列

備用串列

修改串列

“軟”錯誤

零頁面程序

“軟”錯誤

“軟”錯誤

“硬”錯誤刪除頁面 修剪乾淨頁面

必要時

修剪”髒”頁面

修改頁面寫出器

Page 40: Team 7

40

記憶體管理員動態調度的過程,頁面可能會經歷各種變化

實體頁面的狀態轉移

工作集( 行程或系

統 )

歸零串列 空閒串列

備用串列

修改串列

“軟”錯誤

零頁面程序

“軟”錯誤

“軟”錯誤

“硬”錯誤刪除頁面 修剪乾淨頁面

必要時

修剪”髒”頁面

修改頁面寫出器

Page 41: Team 7

41

為解決分頁錯誤,行程會需要一個頁面,它有可能從圖中的 4 個串列其中之一取得實體記憶體頁面

行程取得頁面 - 以分頁錯誤為例 -1

歸零串列 空閒串列 備用串列 修改串列

Page 42: Team 7

42

從修改或備用串列中取得實體頁面分頁錯誤由正在轉移狀態的無效 PTE引起

行程取得頁面 - 以分頁錯誤為例 -2

PTE

分頁框架編號

1.尋找實體頁面

PFN 資料庫項目

MiUnlinkPageFromList 函式

2.呼叫

備用串列 修改串列

3. 該頁面從串列中移除

Page 43: Team 7

43

從空閒 ( 零化或備用 ) 串列取得實體頁面 :分頁錯誤由一位於分頁檔中的 PTE 所引起,分頁錯誤處理常式會透過 MiRemoveAnyPage 函式獲得一實體頁面滿足分頁錯誤。

從零化 ( 空閒或備用 ) 串列取得實體頁面 :若分頁錯誤需要零頁面來滿足此錯誤,則呼叫MiRemoveZeroPage 函式獲得一零化頁面

行程取得頁面 - 以分頁錯誤為例 -3

Page 44: Team 7

44

記憶體管理員動態調度的過程,頁面可能會經歷各種變化

實體頁面的狀態轉移

工作集( 行程或系

統 )

歸零串列 空閒串列

備用串列

修改串列

“軟”錯誤

零頁面程序

“軟”錯誤

“軟”錯誤

“硬”錯誤刪除頁面 修剪乾淨頁面

必要時

修剪”髒”頁面

修改頁面寫出器

Page 45: Team 7

45

空閒串列 -( 零頁面緒程 )-> 零化串列 - MmZeroPageThread 函式

頁面於串列間的轉移 (1/3)

Page 46: Team 7

46

MmZeroPageThread 函式是個無限迴圈,他等待以下兩個事件之一 : MmZeroingPageEvent 和PoSystemIdelTimer

零頁面緒程 (1/2)

零化事件MmZeroingPageEv

ent

2. 空閒串列頁面數大於MmMinimumFreePageToZero= 8

MmZeroPageThread

MiInsertPageInFreeList 函式

空閒串列

3. 通知1.插入頁面

Page 47: Team 7

47

零化操作

重複以上步驟,直至目前空閒串列頁面全部零化

零頁面緒程 (2/2)

零化事件MmZeroingPageE

vent

1.通知MmZeroPageThr

ead

MiInsertPageInList

函式空閒串列MmZeroPageListH

ead

3. 呼叫2. 取得頁面設定成壞頁面指定為零

4. 將頁面插入至

Page 48: Team 7

48

記憶體管理員動態調度的過程,頁面可能會經歷各種變化

實體頁面的狀態轉移

工作集( 行程或系

統 )

歸零串列 空閒串列

備用串列

修改串列

“軟”錯誤

零頁面程序

“軟”錯誤

“軟”錯誤

“硬”錯誤刪除頁面 修剪乾淨頁面

必要時

修剪”髒”頁面

修改頁面寫出器

Page 49: Team 7

49

備用串列 -(必要時 )-> 空閒串列一般情況下,備用串列頁面不會主動地轉移到空閒串列中,除非這些頁面已經確定不被使用了。

發生轉移的例子 :當行程刪除一段記憶體時,包括行程、程序結束時清除記憶體做的操作 ( 發生在 MiDeleteVirtualAddresses 函式中 )

頁面於串列間的轉移 (2/3)

Page 50: Team 7

50

MiDeleteVirtualAddresses 函式被呼叫到,會把不再共用的有效頁面轉移到空閒串列中,也就是從工作集刪除頁面,見圖 4.29

此過程發生如下 :

從工作集「刪除頁面」

MiDeleteVirtualAddresses

函式

MiDecrementShareCount 函式MiDeletePte

函式 共用計數器

空閒串列

1. 呼叫

共用計數器減 1為 0引用計數器為 1

2. 呼叫 引用計數器

工作集轉移頁面

Page 51: Team 7

51

當可用行程記憶體數量很少時,記憶體管理員修剪行程或系統工作集,這工作由MmWorkingSetManager( 工作集管理員 ) 函式的元件完成

工作集修剪

工作集( 行程或系

統 )

歸零串列 空閒串列

備用串列

修改串列

“軟”錯誤

零頁面程序

“軟”錯誤

“軟”錯誤

“硬”錯誤刪除頁面 修剪乾淨頁面

必要時

修剪”髒”頁面

修改頁面寫出器

Page 52: Team 7

52

記憶體管理員動態調度的過程,頁面可能會經歷各種變化

實體頁面的狀態轉移

工作集( 行程或系

統 )

歸零串列 空閒串列

備用串列

修改串列

“軟”錯誤

零頁面程序

“軟”錯誤

“軟”錯誤

“硬”錯誤刪除頁面 修剪乾淨頁面

必要時

修剪”髒”頁面

修改頁面寫出器

Page 53: Team 7

53

修改串列 -( 修改頁面寫出器 )-> 備用串列隨著工作集的頁面被加到修改串列中,修改串列會變大。到一定程度,記憶體管理員要將修改串列的頁面寫到磁碟上,進而把頁面轉移到備用串列,是利用修改頁面寫出器來完成

頁面於串列間的轉移 (3/3)

Page 54: Team 7

54

2012/6/13

吳藺剛

4.5.3 實體頁面的管理和操作

Page 55: Team 7

55

在 MMPFN 資料結構的 u3.e1 成員,有一個 4 位元的 PageColor欄位,代表一個 PFN 項目的顏色

Color 參數 (1/2)

Typedf struct _MMCOLOR_TABLES{PFN_NUMBER Flink;PVOID Blink;PFN_NUMBER Count;

}MMCOLOR_, *PMMCOLOR_TABLES;Extern PMMCOLOR_TABLES MmFreePagesByColor[2];

Page 56: Team 7

56

初始化在 MiInitMachineDependent 函式,與MmSecondaryColors 和MmSecondaryColorsMask 有關

例如 MmFreePagesByColor[0][0]代表顏色為 0的零化頁面串列, MmFreePagesByColor[1][0]代表顏色為 0 的空閒頁面串列開頭

Color 參數 (2/2)

Page 57: Team 7

57

空閒頁面的插入 (1/2)MiInsertPageInFreeList00638 /* Get the last page on the list */00639 LastPage = ListHead->Blink;00640 if (LastPage != LIST_HEAD)00641 {00642 /* Link us with the previous page, so we're at the end now */00643 MI_PFN_ELEMENT(LastPage)->u1.Flink = PageFrameIndex;00644 }00645 else00646 {00647 /* The list is empty, so we are the first page */00648 ListHead->Flink = PageFrameIndex;00649 }00650 00651 /* Now make the list head point back to us (since we go at the end) */00652 ListHead->Blink = PageFrameIndex;00653 ASSERT_LIST_INVARIANT(ListHead);00654 00655 /* And initialize our own list pointers */00656 Pfn1->u1.Flink = LIST_HEAD;00657 Pfn1->u2.Blink = LastPage;

Page 58: Team 7

58

空閒頁面的插入 (2/2)00682 /* Get the page color */00683 Color = PageFrameIndex & MmSecondaryColorMask;00684 00685 /* Get the first page on the color list */00686 ColorTable = &MmFreePagesByColor[FreePageList][Color];00687 if (ColorTable->Flink == LIST_HEAD)00688 {00689 /* The list is empty, so we are the first page */00690 Pfn1->u4.PteFrame = COLORED_LIST_HEAD;00691 ColorTable->Flink = PageFrameIndex;00692 }00693 else00694 {00695 /* Get the previous page */00696 Blink = (PMMPFN)ColorTable->Blink;00697 00698 /* Make it link to us, and link back to it */00699 Blink->OriginalPte.u.Long = PageFrameIndex;00700 Pfn1->u4.PteFrame = MiGetPfnEntryIndex(Blink);00701 }00702 00703 /* Now initialize our own list pointers */00704 ColorTable->Blink = Pfn1;

Page 59: Team 7

59

零化頁面的插入 (1/2)MiInsertPageInFreeList00868 /* Zero pages go to the head, all other pages go to the end */00869 if (ListName == ZeroedPageList)00870 {00871 /* Make the head of the list point to this page now */00872 Flink = ListHead->Flink;00873 ListHead->Flink = PageFrameIndex;00874 00875 /* Make the page point to the previous head, and back to the list */00876 Pfn1->u1.Flink = Flink;00877 Pfn1->u2.Blink = LIST_HEAD;00878 00879 /* Was the list empty? */00880 if (Flink != LIST_HEAD)00881 {00882 /* It wasn't, so update the backlink of the previous head page */00883 Pfn2 = MI_PFN_ELEMENT(Flink);00884 Pfn2->u2.Blink = PageFrameIndex;00885 }00886 else00887 {00888 /* It was empty, so have it loop back around to this new page */00889 ListHead->Blink = PageFrameIndex;00890 }

Page 60: Team 7

60

零化頁面的插入 (2/2)00941 /* Get the page color */00942 Color = PageFrameIndex & MmSecondaryColorMask;00943 00944 /* Get the list for this color */00945 ColorHead = &MmFreePagesByColor[ZeroedPageList][Color];00946 00947 /* Get the old head */00948 Flink = ColorHead->Flink;00949 00950 /* Make this page point back to the list, and point forwards to the old head */00951 Pfn1->OriginalPte.u.Long = Flink;00952 Pfn1->u4.PteFrame = COLORED_LIST_HEAD;00953 00954 /* Set the new head */00955 ColorHead->Flink = PageFrameIndex;

Page 61: Team 7

61

從串列開頭移除一個零化或空閒頁面1. 在 MiRemovePageFromList 函式中,先從指定的串列開頭移除一個頁面,然後更新顏色串列。2. 在 MiRemovePageByColor 函式中,根據指定顏色和頁面 PFN 從串列開頭移除頁面,並更新顏色串列

00364 /* Get the PFN entry */00365 Pfn1 = MI_PFN_ELEMENT(PageIndex);00366 ASSERT(Pfn1->u3.e1.RemovalRequested == 0);00367 ASSERT(Pfn1->u3.e1.Rom == 0);

00379 /* Remove a page */00380 ListHead->Total--;

00414 /* Zero flags but restore color and cache */00415 Pfn1->u3.e2.ShortFlags = 0;00416 Pfn1->u3.e1.PageColor = OldColor;00417 Pfn1->u3.e1.CacheAttribute = OldCache;00418 00419 /* Get the first page on the color list */00420 ASSERT(Color < MmSecondaryColors);00421 ColorTable = &MmFreePagesByColor[ListName][Color];00422 ASSERT(ColorTable->Count >= 1);00423 00424 /* Set the forward link to whoever we were pointing to */00425 ColorTable->Flink = Pfn1->OriginalPte.u.Long;

Page 62: Team 7

62

用法:MMPFN 用三位元描述一個頁面的優先順序 0-7 ,有 8 個備用串列飛別存放各個優先順序的頁面EX:MmStandByPageListByPriority

在 WRK 中,備用串列 MmStandbyPageListHead雖然有定義,但並沒有真實用到,真正的備用串列是MmStandybyPageListByPriority陣列

備用串列

Page 63: Team 7

63

在串列前端插入備用頁面 (1/2)1.MiInsertStandbyListAtFront00743 /* Grab the PFN and validate it is the right kind of PFN being inserted */00744 Pfn1 = MI_PFN_ELEMENT(PageFrameIndex);00745 ASSERT(Pfn1->u4.MustBeCached == 0);00746 ASSERT(Pfn1->u3.e2.ReferenceCount == 0);00747 ASSERT(Pfn1->u3.e1.PrototypePte == 1);00748 ASSERT(Pfn1->u3.e1.Rom != 1);00749 00750 /* One more transition page on a list */00751 MmTransitionSharedPages++;00752 00753 /* Get the standby page list and increment its count */00754 ListHead = &MmStandbyPageListByPriority [Pfn1->u4.Priority];00755 ASSERT_LIST_INVARIANT(ListHead);00756 ListHead->Total++;00757 00758 /* Make the head of the list point to this page now */00759 Flink = ListHead->Flink;00760 ListHead->Flink = PageFrameIndex;00761 00762 /* Make the page point to the previous head, and back to the list */00763 Pfn1->u1.Flink = Flink;00764 Pfn1->u2.Blink = LIST_HEAD;

Page 64: Team 7

64

在串列前端插入備用頁面 (2/2)2. 在 MiInsertPageList 函式中,即使參數中只訂了 MmStandbyPageListHead 作為串列開頭,真正的目標串列開頭也要轉變成 MmStandbyPageKistByPriority 陣列中對應優先順序的串列。

00838 /* Standby pages are prioritized, so we need to get the real head */00839 if (ListHead == &MmStandbyPageListHead)00840 {00841 /* Obviously the prioritized list should still have the same name */00842 ListHead = &MmStandbyPageListByPriority[Pfn1->u4.Priority];00843 ASSERT(ListHead->ListName == ListName);00844 }

Page 65: Team 7

65

在串列中移除一個備用頁面在 MiRemovePageFromList 函式中,如果要移除備用頁面,客戶程式碼不能指定 MmStandbyPageListHead 作為備用串列,而必須是MmStandbyPageListByPriority 陣列的一個成員。 MiRestoreTransitionPte 函式中,移除一個節點,對於一個備用頁面,其對應的 PTE 會處於轉移狀態,所以頁面移除後,須恢復對應 PTE 的內容,而不再處於轉移狀態

00254 // Remove page, but leave its status as idle.00255 Pfn->u3.e1.Location = StandbyPageList;0025600257 MiRestoreTransitionPte (PageFrameIndex);00258 MiInsertPageInList (MmPageLocationList[BadPageList],PageFrameNumber);00269 return;

Page 66: Team 7

66

在串列中間移除一個備用頁面在 MiUnlinkPageFromList 函式中,如果根據頁面 PFN 項目得到的串列是 MmStandbyPageListHead ,則將串列轉換為MmStandbyPageListByPriority 陣列中對應的串列00247 /* Check if this was standby, or modified */00248 if (ListHead == &MmStandbyPageListHead)00249 {00250 /* Should not be a ROM page */00251 ASSERT(Pfn->u3.e1.Rom == 0);00252 00253 /* Get the exact list */00254 ListHead = &MmStandbyPageListByPriority[Pfn->u4.Priority];00255 00256 /* See if we hit any thresholds */00257 if (MmAvailablePages == MmHighMemoryThreshold)00258 {00259 /* Clear the high memory event */00260 KeClearEvent(MiHighMemoryEvent);00261 }00262 else if (MmAvailablePages == MmLowMemoryThreshold)00263 {00264 /* Signal the low memory event */00265 KeSetEvent(MiLowMemoryEvent, 0, FALSE);00266 }

Page 67: Team 7

67

分成兩部分:頁面 PFN 項目的 OriginalPre.u.Soft.Prototype 位元欄位為 0 則該頁面被置於MmModifiedPageListByColor[0] 中,外部記憶體位置是分頁檔

其餘頁面被放在全域串列 MmModifiedPageListHead中,這些頁面的外部記憶體位置是對應檔案

MmModifiedPageListHead 中的計數值也包括位於分頁檔的那些頁面

修改頁面的插入透過 MiInsertPageInList ,移除透過MiUnlinkPageFromList

修改串列

Page 68: Team 7

68

該串列的頁面被修改了,但記憶體管理員的修改頁面寫出器並不會把這些頁面寫到外部記憶體

透過 MiInsertPageInList 可在該串列尾部插入頁面,透過 MiInsertFrontNodifiedNoWrite 可在該串列前端插入一個頁面, 頁面移除則要靠MiUnlinkPageFromList 完成

MmEnableModifiedWriteOfSectionU.Flags.NoModiefiedWriting旗標位元

修改但不寫出頁面的串列 (1/2)

Page 69: Team 7

69

修改但不寫出頁面的串列 (2/2)MmEnableModifiedWriteOfSection

4657 // Move any straggling pages on the modnowrite list back onto the modified list otherwise they would be orphaned and this could cause us to run out of pages.4658 if (MmModifiedNoWritePageListHead.Total != 0) {4659 PageFrameIndex = MmModifiedNoWritePageListHead.Flink;4660 do {4661 Pfn1 = MI_PFN_ELEMENT (PageFrameIndex);4662 NextPageFrameIndex = Pfn1->u1.Flink;4663 Subsection = MiGetSubsectionAddress (&Pfn1->OriginalPte);4664 if (ControlArea == Subsection->ControlArea) {4665 // This page must be moved to the modified list.4666 MiUnlinkPageFromList (Pfn1);4667 MiInsertPageInList (&MmModifiedPageListHead,PageFrameIndex);4668 }4669 PageFrameIndex = NextPageFrameIndex;4670 } while (PageFrameIndex != MM_EMPTY_LIST);

Page 70: Team 7

70

NTFS 檔案系統利用這種頁面來對應檔案系統中繼資料,所以,這些資料不會自動寫上磁碟上,當紀錄中繼資料修改情況的日誌資訊被寫到磁碟上後,才允許中繼資料寫上

保證中繼資料的修改均有紀錄,若發生意外,中繼資料可以恢復

副作用是這些頁面將占據系統實體記憶體,所以客戶有責任確保不會累積太多,且透過MmEnableModifiedWriteOfSection 將他移除

修改但不寫出頁面的經典用途

Page 71: Team 7

71

相對簡單,並不參與系統頁面調度,透過MiInsertPageInList 可以將一個壞頁面插入MmBadPageListHead 串列

若零化、空閒或備用頁面的 PFN 項目的u3.e1.RemovalReaquested 位元欄,被設定,則被插入到會頁面串列

壞頁面插入後就不再移除

壞頁面串列

Page 72: Team 7

72

MiRemoveZeroPage00549 /* Check the colored zero list */00550 PageIndex = MmFreePagesByColor[ZeroedPageList][Color].Flink;00551 if (PageIndex == LIST_HEAD)00552 {00553 /* Check the zero list */00554 ASSERT_LIST_INVARIANT(&MmZeroedPageListHead);00555 PageIndex = MmZeroedPageListHead.Flink;00556 if (PageIndex == LIST_HEAD)00557 {00558 /* This means there's no zero pages, we have to look for free ones */00559 ASSERT(MmZeroedPageListHead.Total == 0);00560 Zero = TRUE;00561 00562 /* Check the colored free list */00563 PageIndex = MmFreePagesByColor[FreePageList][Color].Flink;00564 if (PageIndex == LIST_HEAD)00565 {00566 /* Check the free list */00567 ASSERT_LIST_INVARIANT(&MmFreePageListHead);00568 PageIndex = MmFreePageListHead.Flink;00569 Color = PageIndex & MmSecondaryColorMask;00570 ASSERT(PageIndex != LIST_HEAD);00571 if (PageIndex == LIST_HEAD)00572 {00573 /* FIXME: Should check the standby list */00574 ASSERT(MmZeroedPageListHead.Total == 0);00575 }00576 }00577 }00578 else00579 {00580 Color = PageIndex & MmSecondaryColorMask;00581 }00582 }

Page 73: Team 7

73

MiRemoveAnyPage00492 /* Check the colored free list */00493 PageIndex = MmFreePagesByColor[FreePageList][Color].Flink;00494 if (PageIndex == LIST_HEAD)00495 {00496 /* Check the colored zero list */00497 PageIndex = MmFreePagesByColor[ZeroedPageList][Color].Flink;00498 if (PageIndex == LIST_HEAD)00499 {00500 /* Check the free list */00501 ASSERT_LIST_INVARIANT(&MmFreePageListHead);00502 PageIndex = MmFreePageListHead.Flink;00503 Color = PageIndex & MmSecondaryColorMask;00504 if (PageIndex == LIST_HEAD)00505 {00506 /* Check the zero list */00507 ASSERT_LIST_INVARIANT(&MmZeroedPageListHead);00508 PageIndex = MmZeroedPageListHead.Flink;00509 Color = PageIndex & MmSecondaryColorMask;00510 ASSERT(PageIndex != LIST_HEAD);00511 if (PageIndex == LIST_HEAD)00512 {00513 /* FIXME: Should check the standby list */00514 ASSERT(MmZeroedPageListHead.Total == 0);00515 }

Page 74: Team 7

74

Windows 提供用來描述實體記憶的資料結構

存取到包含這些頁面的 PFN

MDL(Memory Descriptor List)

Typedef struct _MDL{Struct _MDL *Next;CSHORT Size;CSHIRT MdlFlags;Struct _EORICESS *Process;POVID MappedSystemVa;ULONG ByteCount;ULONG ByteOffset;

}MDL, *PMDL

Page=(PPFB_NUMBER)(Mdl+1);

Page 75: Team 7

75

PMDL

MDL三個介面函式 (1/3)

MmallocatePageForMdl(__in PHYSICAL_ADDRESS LowAddress,__in PHYSICAL_ADDRESS HighAddress,__in PHYSICAL_ADDRESS SkipBytes,__in Size_T TotalBytes

);

Page 76: Team 7

76

PMDL

MDL三個介面函式 (2/3)

MmAllocatePagesForMdlEx(__in PHYSICAL_ADDRESS LowAddress,__in PHYSICAL_ADDRESS HighAddress__in Size_T TotalBytes,__in MEMORY_CACHING_TYPE CacheType,__in ULONG Flags

);

Page 77: Team 7

77

VOID

MDL三個介面函式 (3/3)

MmFreePagesFroMdl(__in PMDL MemoryDescriptorList

);

Page 78: Team 7

78

為在指定的位址範圍內獲得足夠的記憶體, MiAllocatePagesForMDl 函式搜尋零化、空閒和備用串列,盡可能滿足的記憶體需求。但函式回傳時,實際申請到的記憶體頁面數有可能少於客戶要求數量,所以必須檢查結果 MDL 物件中的成員值

MiAllocatePagesForMdl 並不將這些實體記憶體對應到虛擬位址空間,若需要虛擬位址,則須自己對應

MmFreePagesFromMdl 函式負責把實體記憶體歸還 PFN 資料庫

MDL

Page 79: Team 7

79

2012/6/13

洪國勛劉乃菀

4.5.4 修改頁面寫出器

Page 80: Team 7

80

當系統 memory消耗很多,零化序列、空閒序列和備用序列上的 page 數會減少,當少到一定程度時,修改頁面寫出器 (modified page writer)就會啟動,將已修改的頁面寫到外部記憶體中

Modified page writer主要做兩種工作:負責往「分頁檔」中寫頁面負責往「對應檔案」中寫頁面

一旦頁面內容被寫到外部記憶體,這些頁面就會被轉移到備用序列中,供系統或其他 Process 使用

Modified Page Writer (1/2)

Page 81: Team 7

81

當記憶體管理員初始化時, MmInitSystem 函式會建立一個系統緒程,其啟動程序為MiModifiedPageWriter , modified page writer 在即此實作

MiModifiedPageWriter 執行後會建立第二個緒程 MiMappedPageWriter

此兩個緒程都屬於即時優先順序,有較高優先權

Modified Page Writer (2/2)

Page 82: Team 7

82

MiModifiedPageWriter

初始化

啟動對應頁面寫出緒程

呼叫 MiModifiedPageWriterWorker函式

分頁檔的寫入操作 對應檔案頁面寫入操作

呼叫 MiGatherPagefilePages函式

呼叫 MiGatherMappedPages函式

等待事件訊號

事件觸發

無窮迴圈等待事件

Page 83: Team 7

83

使用 PsCreateSystemThread 函數創建一個新的SystemThread

啟動MiModifiedPageWriter

InitializeObjectAttributes (&ObjectAttributes, NULL, 0, NULL, NULL);if (!NT_SUCCESS(PsCreateSystemThread (

&ThreadHandle,THREAD_ALL_ACCESS,&ObjectAttributes, 0L,NULL,MiModifiedPageWriter, /* 啟動的函式 */NULL))) {

return FALSE;}

Page 84: Team 7

84

MiModifiedPageWriter初始化/* Initialize listheads as empty. */MmSystemShutdown = 0;KeInitializeEvent (&MmPagingFileHeader.Event, NotificationEvent, FALSE);KeInitializeEvent (&MmMappedFileHeader.Event, NotificationEvent, FALSE);

InitializeListHead(&MmPagingFileHeader.ListHead);InitializeListHead(&MmMappedFileHeader.ListHead);InitializeListHead(&MmFreePagingSpaceLow);

MmNumberOfMappedMdls = MmNumberOfPhysicalPages / (32 * 1024);

/* Allocate enough MDLs */if (MmNumberOfMappedMdls < 20) {

MmNumberOfMappedMdls = 20;}

Page 85: Team 7

85

啟動MiMappedPageWriter

InitializeObjectAttributes (&ObjectAttributes, NULL, 0, NULL, NULL);Status = PsCreateSystemThread (

&ThreadHandle,THREAD_ALL_ACCESS,&ObjectAttributes,0L,NULL,MiMappedPageWriter, /* 啟動的函式 */NULL);

ZwClose (ThreadHandle);MiModifiedPageWriterWorker (); /* 啟動MiModifiedPageWriterWorker */

Page 86: Team 7

86

MmModifiedPageWriterEvent觸發條件 (擇一 )

已修改過的 page 數超過預設上限可用 page 數少於 256 且修改串列中的 page 數達到預設上限

觸發後應獲得信號 (擇一 )寫入「分頁檔」寫入「對應檔」

MiMappedPagesTooOLdEvent每隔 300秒觸發一次防止對應檔案中的資料修改之後由於系統當機等意外事故造成大量資料未能及時刷新到外部記憶體

MiModifiedPageWriterWorker

Page 87: Team 7

87

MmModifiedPageWriterEvent

if (MmAvailablePages < MM_PLENTY_FREE_LIMIT) {/* If necessary, start the modified page writer. */if (MmModifiedPageListHead.Total >=

MmModifiedPageMaximum) {KeSetEvent (&MmModifiedPageWriterEvent, 0,

FALSE);}else if ((MmAvailablePages < MM_TIGHT_LIMIT) &&(MmModifiedPageListHead.Total >=

MmModifiedWriteClusterSize)) { KeSetEvent (&MmModifiedPageWriterEvent, 0, FALSE);

}}

可用 page數之預設上限

已修改過的page 數之預設上限

修改串列中的page 數之預設上限

Page 88: Team 7

88

分頁檔的寫入流程

掃描分頁檔點陣圖

檢查修改串列中的已修改頁面

其 PTE 設置於分頁檔中

設置 PNF 項目的寫入旗標位元

呼叫 IoAsynchronousPageWrite函式

start尋找連續空閒的 page

Page 89: Team 7

89

發出寫入操作

呼叫 IoAsynchronousPageWrite函式

/* Issue the write request. */Status = IoAsynchronousPageWrite (File,

&ModWriterEntry->Mdl,&StartingOffset,MiWriteComplete,(PVOID)ModWriterEntry,IrpPriority,&ModWriterEntry->u.IoStatus,&ModWriterEntry->Irp);

指定的完成函式

Page 90: Team 7

90

對應檔案的寫入流程

檢查 MmModifiedPageListHead 串列中的頁面

檢查與之相鄰的原型 PTE

將其插入到 MmMappedPageWriterList 中

設置事件 MmModifiedPageWriterEvent 有信號

通知對應頁面寫出器緒程

start

欲找出盡可能多的針對同一對應檔案的已修改頁面

Page 91: Team 7

91

2012/6/13

黃柏軒劉乃菀

4.5.5 行程 / 堆疊交換器

Page 92: Team 7

92

主函式 KeSwapProcessOrStack ,主要執行下列事項:換出 Kernel Stack <KiOutSwapKernelStacks>換出 Process <KiOutSwapProcesses>換入 Process <KiInSwapProcesses>換入 Kernel Stack <KiInSwapKernelStacks>

行程 / 堆疊交換器

Page 93: Team 7

93

記憶體管理員每隔 4 或 8 個他自身的檢查週期 (1秒鐘 ) ,就會設置事件的訊號

當進行一些有關緒程或行程的操作時,例如終止緒程、緒程脫離一個行程、就緒一個緒程等情形,若這些操作有必要換出或換入行程或核心堆疊,也會觸發事件

觸發條件

Page 94: Team 7

94

依序檢查 Waiting-In list上的 Thread ,若發現某個 Thread 已經等待超過 stack protect time 則將該 Thread 換出

執行前要先升高 IRQL(Interrupt Request Level)並 lock住資料庫

換出 Kernel Stack (1/6)

KiLockDispatcherDatabase(&OldIrql);

Page 95: Team 7

95

Define kernel stack protect time:若在小記憶體系統則設為 3秒其餘系統則設為 5x秒

換出 Kernel Stack (2/6)

#define SMALL_SYSTEM_STACK_PROTECT_TIME (3 * 75)#define LARGE_SYSTEM_STACK_PROTECT_TIME (SMALL_SYSTEM_STACK_PROTECT_TIME * 5)

:KiStackProtectTime =

LARGE_SYSTEM_STACK_PROTECT_TIME;

Page 96: Team 7

96

從等待串列中提取至多 5 個滿足條件的緒程,並將他們從等待串列中移除

換出 Kernel Stack (3/6)

#define MAXIMUM_THREAD_STACKS 5:

while ((NextEntry != &Prcb->WaitListHead) && (NumberOfThreads <

MAXIMUM_THREAD_STACKS)) {:

}

Page 97: Team 7

97

換出 Kernel Stack (4/6)

if ( WaitLimit < Thread->WaitTime ) {break;

} else if (Thread->Priority >= (LOW_REALTIME_PRIORITY +

9)) {RemoveEntryList(&Thread->WaitListEntry);

}else if (KiIsThreadNumericStateSaved(Thread)) {

ThreadObjects[NumberOfThreads] = Thread; NumberOfThreads += 1; RemoveEntryList(&Thread->WaitListEntry);

Process->StackCount -= 1;}

Page 98: Team 7

98

如果某 Process 的所有 Thread 都被換出,則該行程會被放到行程換出串列

Unlock 資料庫並降低 IRQL

換出 Kernel Stack (5/6)

if (Process->StackCount == 0)Process->State = ProcessOutTransition;

KiUnlockDispatcherDatabase(OldIrql);

Page 99: Team 7

99

Increment the last processor number.

執行換出 Kernel Stack

換出 Kernel Stack (6/6)

KiLastProcessor += 1;if (KiLastProcessor == (ULONG)KeNumberProcessors) {

KiLastProcessor = 0;}

while (NumberOfThreads > 0) { NumberOfThreads -= 1; Thread = ThreadObjects[NumberOfThreads]; MmOutPageKernelStack(Thread);

}

Page 100: Team 7

100

所謂換出行程,實際上就是依序換出四個頁面:工作集串列頁面VAD點陣圖頁面超空間分頁表頁面分頁目錄頁面

只有當一個 Process 的工作集已經降到最小,該行程才會在函式中被換出,否則,工作集管理員會修剪該Process 的工作集,直到被修剪為最小工作尺寸時,該行程才會再次被觸發換出操作

換出 Process (1/2)

Page 101: Team 7

101

依次檢查串列中的每一個 Process ,若該 Process的就緒緒程串列為空,則將之換出

若該 Process 的就緒緒程串列仍然為空,則將之移出記憶體

換出 Process (2/2)

if (NextEntry != &Process->ReadyListHead) {:

} else {Process->State = ProcessOutSwap;MmOutSwapProcess(Process);

}

Process->State = ProcessOutOfMemory;

Page 102: Team 7

102

對於已被換出的行程,只要他有一個緒程就緒,他就會被加入到串列中,並依次恢復四個頁面:分頁目錄頁面超空間分頁表頁面VAD點陣圖頁面工作集串列頁面

換入 Process

Page 103: Team 7

103

要換入 Kernel stack 的 Threads構成了一個串列KiStackInSwapListHead

當一個 Thread 變成就緒時,若是這個 Thread 的Kernel stack 不在記憶體中,則該 Thread就會被加入到串列中

函式會依次處理串列中的每一個 Thread ,執行實際的換入操作

換入 Kernel Stack

MmInPageKernelStack(Thread);

Page 104: Team 7

104

只能騰出很有限的實體記憶體,且必須要等到行程工作集中的其他頁面 ( 除上述所提到的四個頁面 ) 都被修剪過後才會發生

實際系統中, Process 的換出換入很少發生,一旦發生,常常意味著系統的記憶體不足以承擔目前的工作負載,而且系統的效能會急遽退化

Process 的換出與換入 (1/2)

Page 105: Team 7

105

交換器只是保證行程能夠執行,但無法解決效能瓶頸問題

解決方法增加實體記憶體減輕工作負載

Process 的換出與換入 (2/2)

Page 106: Team 7

106

2012/6/13

黃柏軒劉乃菀

4.5.6 低記憶體通知和高記憶體通知

Page 107: Team 7

107

當系統的可用記憶體很少或很充裕

Process 知道這些事件發生並做出反應

低記憶體通知和高記憶體通知

通知

Page 108: Team 7

108

MmInitSystem

MiInitializeMemoryEvents

Windows 的記憶體管理員的作法

呼叫

Page 109: Team 7

109

條件:可用記憶體低於 Threshold (MmLowMemoryThreshold)

MmLowMemoryThreshold 變數的值由系統實體記憶體的數量決定,除非應用系統在登錄中指定

低記憶體事件的觸發

Page 110: Team 7

110

RAM > 1GB第一個 1GB 為 32MB餘下每 1GB增加 8MB

128MB < RAM < 1GB第一個 128MB 為 3.1MB(800 pages)餘下每 128MB增加 4MB

RAM < 128MB等於 MmPlentyFreeThresholdRAM < 63MB = 400 pages ,否則 = 800 pages

MmLowMemoryThreshold

Page 111: Team 7

111

MmLowMemoryThreshold 的單位需由megabytes 轉換成 pages

MmLowMemoryThreshold

if (MmLowMemoryThreshold != 0) {MmLowMemoryThreshold *= ((1024 * 1024) /

PAGE_SIZE);}

Page 112: Team 7

112

RAM > 1GB

例如:當 RAM = 4GBMmLowMemoryThreshold = 32MB + ((0x100000 – 0x40000) >> 7) *

4K= 32MB + 3 * 8MB = (8K + 3 * 2K) pages

MmLowMemoryThreshold

if (MmNumberOfPhysicalPages > 0x40000) {MmLowMemoryThreshold = (32 * 1024 * 1024) /

PAGE_SIZE;MmLowMemoryThreshold+=((MmNumberOfPhysicalPages -

0x40000) >> 7);}

Page 113: Team 7

113

1GB > RAM > 128MB

例如:當 RAM = 512MBMmLowMemoryThreshold = 3.1MB + ((0x20000 – 0x8000) >> 5) * 4K= 3.1MB + 3 * 4MB = (800 + 3 * 1K) pages

MmLowMemoryThreshold

else if (MmNumberOfPhysicalPages > 0x8000) {MmLowMemoryThreshold += ((MmNumberOfPhysicalPages

- 0x8000) >> 5);}

Page 114: Team 7

114

If MmLowMemoryThreshold > 16K pagesThat is RAM > 5GB

MmLowMemoryThreshold

if (MmLowMemoryThreshold > (64 * 1024 * 1024) / PAGE_SIZE) {MmLowMemoryThreshold = (64 * 1024 * 1024) /

PAGE_SIZE;}

Page 115: Team 7

115

高記憶體事件 Threshold = 低記憶體事件Threshold 的 3倍

高記憶體事件的觸發

if (MmHighMemoryThreshold != 0) {MmHighMemoryThreshold *= ((1024 * 1024) / PAGE_SIZE);

} else {MmHighMemoryThreshold = 3 * MmLowMemoryThreshold;

}

if (MmHighMemoryThreshold < MmLowMemoryThreshold) {MmHighMemoryThreshold = MmLowMemoryThreshold;

}

Page 116: Team 7

116

2012/6/13

卓卿安吳政樺

4.6 工作集管理

Page 117: Team 7

117

工作集 ( Working Set) 是指一個行程目前正在使用的實體頁面的集合

Windows 中有三個工作集概念 行程工作集 系統工作集 工作階段工作集

工作集管理

Page 118: Team 7

4.6.1 Windows 工作集管理員

Page 119: Team 7

每個行程在建立位址空間時會對應一個專門的頁面存放它的工作集串列

其位址放於全域變數 MmWorkingSetList 中,型別為 MMWSL ,定義在下一頁

如何追蹤行程所用的實體頁面

Page 120: Team 7

typedef struct _MMWSL {

WSLE_NUMBER FirstFree; // 工作集空閒串列的起始 WSLE_NUMBER FirstDynamic; // 工作集中第一個可被修剪的頁面WSLE_NUMBER LastEntry // 工作集中最後一個可被修剪的頁面WSLE_NUMBER NextSlot; // 當要修剪頁面時,從此位置開始搜尋頁面

PMMWSLE Wsle;

WSLE_NUMBER LastInitializedWsle;

WSLE_NUMBER NonDirectCount;

PMMWSLE_HASH HashTable;

ULONG HashTableSize;

ULONG NumberOfCommittedPageTables;

PVOID HashTableStart;

PVOID HighestPermittedHashAddress;

ULONG NumberOfImageWaiters;

ULONG VadBitMapHint;

USHORT UsedPageTableEntries[MM_USER_PAGE_TABLE_PAGES];

ULONG CommittedPageTables[MM_USER_PAGE_TABLE_PAGES/(sizeof(ULONG)*8)]

} MMWSL, *PMMWSL;

MMWSL 型別定義

Wsle 是一個指標,實際上指向一個陣列,其陣列成員型別為 MMWSLE ,描述一個有效的頁面, MMWSLE 型別定義如下頁

Page 121: Team 7

工作集串列的組織結構

MMWSL 資料結構中, FirstDynamic 成員指向第一個可被修改的頁面,故在 MiTrimWorkingSet 函式中可看到,工作集修剪都從 FirstDynamic 開始

FirstFree 成員指向一個空閒串列開頭,這些項在內部形成一個單串列

LastEntry 成員指向最後一個使用項,因此MiTrimWorkingSet 在修剪工作集時絕對不會超過 LastEntry 項

Page 122: Team 7

typedef struct _MMWSLENTRY {

ULONG_PTR Valid : 1; // 頁面是否有效ULONG_PTR LockedInWs : 1;

ULONG_PTR LockedInMemory : 1;

ULONG_PTR Protection : 5;

ULONG_PTR Hashed : 1; // 頁面是否已被插入 Hash Table 中ULONG_PTR Direct : 1; // 頁面的 PFN 項目的 WsIndex 直接指向此項的索引ULONG_PTR Age : 2; // 頁面最近多久沒被訪問ULONG_PTR VirtualPageNumber : 20; 

} MMWSLENTRY;

typedef struct _MMWSLE {

union {PVOID VirtualAddress;ULONG_PTR Long;MMWSLENTRY e1;

} u1;

} MMWSLE;

MMWSLE 型別定義

高 20 位元是頁面的虛擬位址低 12 位元是 MMWSLENTRY 中定義的旗標位元

Page 123: Team 7

工作集的最小值在行程建立時設定的, MmCreateProcessAddressSpace 函式的第一個參數

MmCreateProcessAddressSpace(

IN ULONG MinimumWorkingSetSize,

IN PEPROCESS NewProcess,

OUT PULONG_PTR DirectoryTableBase

);

在 4.3.1 節所述, WRK 中預設最小值是 50 ( 對於超過 32MB 記憶體的系統 ) ,最大值是 345 。

工作集的最小值和最大值

Page 124: Team 7

當行程使用很多頁面,並且系統確實有足夠的可用頁面時,行程工作集可以超越原本設定的最大值,但不能超過系統設定的一個全域最大值 MmMaximumWorkingSetSize ,是在系統初始化就設定好

MmMaximumWorkingSetSize = (WSLE_NUMBER)(MmAvailablePages - 512);

當系統記憶體吃緊時,而且行程不需用到很多頁面時,工作集可能降低到最小值以下

工作集的最小值和最大值

Page 125: Team 7

• 在 4.5 節中提到,記憶體管理員包含一個工作集管理員,會定期檢查各個行程的工作集,為了有效的使用實體記憶體,必要時須修剪占用記憶體較多的行程工作集。

• 在行程 EPROCESS 資料結構 中 VM 成員,其型別為 MMSUPPORT ,包含了工作集管理員在判斷是否需要修剪一個行程所需的各種資訊。

修剪工作集

Page 126: Team 7

typedef struct _MMSUPPORT {LIST_ENTRY WorkingSetExpansionLinks; LARGE_INTEGER LastTrimTime;

MMSUPPORT_FLAGS Flags;ULONG PageFaultCount;WSLE_NUMBER PeakWorkingSetSize;WSLE_NUMBER GrowthSinceLastEstimate;

WSLE_NUMBER MinimumWorkingSetSize; // 工作集最小值WSLE_NUMBER MaximumWorkingSetSize; // 工作集最小值struct _MMWSL *VmWorkingSetList; // 工作集虛擬地址指針WSLE_NUMBER Claim; //工作集老化情況評估值

WSLE_NUMBER NextEstimationSlot;WSLE_NUMBER NextAgingSlot;WSLE_NUMBER EstimatedAvailable;WSLE_NUMBER WorkingSetSize; // 工作集目前大小

EX_PUSH_LOCK WorkingSetMutex;} MMSUPPORT, *PMMSUPPORT;

MMSUPPORT 型別定義如果行程允許被修剪,其EPROCESS 的 Vm.WorkingSetExpansionLinks 會被加入到一個以全域變數 MmWorkingSetExpansionHead 為串列開頭的串列中

Page 127: Team 7

工作集結構

Page 128: Team 7

工作集管理員的執行流程圖

Page 129: Team 7

VOID KeBalanceSetManager (IN PVOID Context) {

switch (Status) {

.....

case WorkingSetManagerEvent:

MmWorkingSetManager();

break;

…..

}

}

VOID MmWorkingSetManager (VOID) {

.....

WorkingSetRequestFlags = MiComputeSystemTrimCriteria (&TrimCriteria);

if (WorkingSetRequestFlags != 0) {

MiProcessWorkingSets (WorkingSetRequestFlags, &TrimCriteria);

}

…..

}

工作集管理員的執行

呼叫MiComputerSystemTrimCriteria 函式以確定是否需要啟動修剪工作集或刷新工作集年齡

在記憶體管理員的平衡集管理員緒程中被呼叫,每隔 1 秒被觸發 1 次,或是當可用的記憶體降低至某一界限時觸發

Page 130: Team 7

ULONG MiComputeSystemTrimCriteria (IN PMMWS_TRIM_CRITERIA Criteria) {

.....

if ((Available <= PlentyFreePages) ||

(MiReplacing == TRUE) ||

(StandbyRemoved >= (Available >> 2))) {

MiRearrangeWorkingSetExpansionList ();

OutFlags = MI_TRIM_ALL_WORKING_SETS;

}

else if (Available < MM_ENORMOUS_LIMIT) {

OutFlags = MI_AGE_ALL_WORKING_SETS;

}

else {

OutFlags = 0;

}

.....

}

MmWorkingSetExpansionHead 串列中的工作集分成不同類別,並按照修剪優先順序重新排序EPROCESS 的 Vm->Claim 越大,放在修剪串列的前部,行程閒置時間越長放在串列前部。

工作集管理員的執行 (Cont.)

1. 目前系統可用頁面數Available少於當前需要的頁面數2. 目前工作集中,已經有被替換頁面的記錄3. 有超過系統可用頁面數四分之一的頁面被重新循環利用當作備用頁面

Page 131: Team 7

VOID KeBalanceSetManager (IN PVOID Context) {

switch (Status) {

.....

case WorkingSetManagerEvent:

MmWorkingSetManager();

break;

…..

}

}

VOID MmWorkingSetManager (VOID) {

.....

WorkingSetRequestFlags = MiComputeSystemTrimCriteria (&TrimCriteria);

if (WorkingSetRequestFlags != 0) {

MiProcessWorkingSets (WorkingSetRequestFlags, &TrimCriteria);

}

…..

}

工作集管理員的執行

呼叫 MiProcessWorkingSets 函式實際修剪或刷新工作集年齡

Page 132: Team 7

VOID MiProcessWorkingSets (IN ULONG WorkingSetRequestFlags, IN PMMWS_TRIM_CRITERIA TrimCriteria) {

…..

if (WorkingSetRequestFlags & MI_TRIM_ALL_WORKING_SETS) {

Trim = MiDetermineTrimAmount (TrimCriteria, VmSupport);

if ((Trim != 0) && ((TrimCriteria->TrimAllPasses > TrimCriteria->NumPasses) ||

(MmAvailablePages < TrimCriteria->DesiredFreeGoal))) {

Trim = MiTrimWorkingSet (Trim, VmSupport, TrimCriteria->TrimAge);

MiAgeWorkingSet (VmSupport, TrimCriteria->DoAging, NULL, &TrimCriteria->NewTotalClaim,

&TrimCriteria->NewTotalEstimatedAvailable);

}

}

else if (WorkingSetRequestFlags & MI_AGE_ALL_WORKING_SETS) {

MiAgeWorkingSet (VmSupport, TRUE, &WslesScanned, &TrimCriteria->NewTotalClaim,

&TrimCriteria->NewTotalEstimatedAvailable);

}

修剪工作集或刷新工作集年齡MiDetermineTrimAmount確定是否需要修剪此 Process 工作集以及修剪多老的頁面,並傳回修剪頁面數量MiTrimWorkingSet

執行修剪工作,在參數中指定:期望從工作集中修剪多少頁面、工作集資訊,以及修剪多老的頁面

MiAgeWorkingSet更新工作集中頁面的年齡值估計改行程工作集的 Vm->Claim 值

Page 133: Team 7

WSLE_NUMBER MiTrimWorkingSet (IN WSLE_NUMBER Reduction, IN PMMSUPPORT WsInfo, IN ULONG TrimAge){ ….. NumberLeftToRemove = Reduction; TryToFree = WorkingSetList->NextSlot; if (TryToFree > LastEntry || TryToFree < WorkingSetList->FirstDynamic) { TryToFree = WorkingSetList->FirstDynamic; } StartEntry = TryToFree; while (NumberLeftToRemove != 0) { …… WsleFlushList.FlushIndex[WsleFlushList.Count] = TryToFree; WsleFlushList.Count += 1; NumberLeftToRemove -= 1; …… TryToFree += 1; } …..}}

執行修剪工作

判斷搜尋的起始位置是否在有效頁面內

從 TryToFree開始迴圈搜索移除頁面

將其編號放 WsleFlushlist中

預計要刪除的頁面數 = 0時停止

Page 134: Team 7

WSLE_NUMBER MiTrimWorkingSet (IN WSLE_NUMBER Reduction, IN PMMSUPPORT WsInfo, IN ULONG TrimAge){ ….. if (WsleFlushList.Count != 0) { NumberNotFlushed = MiFreeWsleList (WsInfo, &WsleFlushList); NumberLeftToRemove += NumberNotFlushed; …… } …… if (WorkingSetList->FirstDynamic == WsInfo->WorkingSetSize) { MiRemoveWorkingSetPages (WsInfo); } else { if ((WsInfo->WorkingSetSize + 15 + (PAGE_SIZE / sizeof(MMWSLE))) < WorkingSetList->LastEntry) _ { if ((WsInfo->MaximumWorkingSetSize + 15 + (PAGE_SIZE / sizeof(MMWSLE))) < WorkingSetList->LastEntry ) { MiRemoveWorkingSetPages (WsInfo); } } }

釋放頁面

將要被釋放的頁面變成轉移狀態,轉移至備用串列或修改串列,並呼叫 MiRemoveWlse 函式將這些頁面移除

MiFreeWsleList 函式只是把被移除了頁面在陣列中做了無效的標記,所以如果 MiTrimWorkingSet 函式完成修剪工作後,發現工作集串列中存在許多無效的頁面,就會呼叫 MiRemoveWorkingSetPages 壓縮工作集串列,清除無效的資料

Page 135: Team 7

VOID MiAgeWorkingSet (IN PMMSUPPORT VmSupport, IN LOGICAL DoAging, IN PWSLE_NUMBER WslesScanned, IN OUT PPFN_NUMBER TotalClaim, IN OUT PPFN_NUMBER TotalEstimatedAvailable)

{

…..

PointerPte = MiGetPteAddress (Wsle[CurrentEntry].u1.VirtualAddress);

if (MI_GET_ACCESSED_IN_PTE(PointerPte) == 1) {

MI_RESET_WSLE_AGE(PointerPte, &Wsle[CurrentEntry]);

}

else {

MI_INC_WSLE_AGE(PointerPte, &Wsle[CurrentEntry]);

}

…...

}

更新工作集年齡

判斷頁面 PTE 的”存取過”位元是否已設定,如果被設定了,代表這個頁面從上次檢查以後已經被存取過,於是年齡值為 0 ,並清除該位

如果”存取過”位元未被設定,則代表上次檢查以來此頁面未被存取過,於是年齡值加 1 ,最大不超過

3

Page 136: Team 7

• MMWSL 使用雜湊表, 即 HashTable 成員,以加速 WSLE 的搜尋過程

由於 Wsle 和 HashTable 位於行程位址空間的固定位置處,空間管理方式直接以頁面對應做管理,而不是透過記憶體集區管理, HashTable 所佔據的頁面也算在工作集內

HashTable 成員

Page 137: Team 7

HashTable 成員typedef struct _MMWSL {

WSLE_NUMBER FirstFree; // 工作集空閒串列的起始 WSLE_NUMBER FirstDynamic; // 工作集中第一個可被修剪的頁面WSLE_NUMBER LastEntry // 工作集中最後一個可被修剪的頁面WSLE_NUMBER NextSlot; // 當要修剪頁面時,從此位置開始搜尋頁面

PMMWSLE Wsle;

WSLE_NUMBER LastInitializedWsle;

WSLE_NUMBER NonDirectCount;

PMMWSLE_HASH HashTable;

ULONG HashTableSize;

ULONG NumberOfCommittedPageTables;

PVOID HashTableStart;

PVOID HighestPermittedHashAddress;

ULONG NumberOfImageWaiters;

ULONG VadBitMapHint;

USHORT UsedPageTableEntries[MM_USER_PAGE_TABLE_PAGES];

ULONG CommittedPageTables[MM_USER_PAGE_TABLE_PAGES/(sizeof(ULONG)*8)]

} MMWSL, *PMMWSL;

Page 138: Team 7

每一項指定了一個從頁面虛擬位址到工作集串列陣列索引的關聯

HashTable 成員

Page 139: Team 7

• 以下是雜湊表成員項 MMWSLE_HASH 定義typedef struct _MMWSLE_HASH {

PVOID Key;WSLE_NUMBER Index;

} MMWSLE_HASH, *PMMWSLE_HASH;

以簡單的運算作為虛擬位置的對應並且用線性開放定址法 找到空閒的雜湊桶

HashTable 成員 (Cont.)

Page 140: Team 7

利用公式算出 Key ,然後在雜湊陣列中從 Key 這項開始尋找,直到找到一個空閒項,然後在這一項中插入該頁面所對應的雜湊項

線性開放定址法

Page 141: Team 7

• MiLocateWsle 函式根據參數中提示的索引項目,判斷是否此索引項目指向

此虛擬位址若是,則成功找到工作集串列若否,則利用參數中指定的虛擬位址在雜湊清單中搜尋

若找到,則傳回雜湊項目中的 Index若找不到,則在工作串列中進行線性搜尋, 直至找到為止,若還是找不到,則回傳失敗

以頁面的虛擬位址找到在工作集串列中的項

Page 142: Team 7

4.6.2 平衡集管理員

Page 143: Team 7

平衡集管理員 (balance set manager)系統初始化時建立,是一個系統緒程優先順序 16 ,最低的即時優先順序主要用途為維持系統記憶體資源的平衡

平衡集所有具備資源分配資格的行程的集合

平衡集管理員

Page 144: Team 7

概念當系統記憶體吃緊時

1. 從擁有較多記憶體的行程的工作集中換出一些頁面2. 把不滿足執行條件的行程排除在平衡集之外

實作基本上是工作集管理員的一個容器,為它提供一個執行環境 (每 1秒觸發 1次 )

每隔 4 或 8秒啟動行程 / 堆疊交換器

平衡集管理員

Page 145: Team 7

145

2012/6/13

吳彥諄吳政樺

4.7 記憶體監視工具 MemMon

Page 146: Team 7

146

MemMon 介紹 (1/3)

系統位置空間翰記憶體配置結構

目前系統中實體記憶體使用量和分頁檔頁面使用量

4.5.3節中提到的記憶體串列

Page 147: Team 7

147

MemMon 介紹 (2/3)

分頁使用量以及還有多少分頁

記憶體總量和可提供的記憶體量

分頁集和非分頁集記憶體量

Page 148: Team 7

148

MemMon 使用介紹 (3/3)

所選之行程記憶體配置結構

系統縮目前的行程樹

所選行程之虛擬記憶體資訊

所選行程的工作集資訊

Page 149: Team 7

149

MemMon 實作原理

MemMon

系統記憶體

行程記憶體

GetPerFromanceInfo

GlobalMemoryStatusEx

Module32First

Module32Next

Heap32First

Heap32Next

Thread32First

Thread32Next

CreateToolhelp32SnapshotProcess32First Process32Next

Page 150: Team 7

150

GlobalMemoryStatusEx (1/2)

GlobalMemoryStatusEx Struct MEMORYSTATUSEX

Header: winbase.h (Windows.h)

<<use>>

<<contant>><<contant>>

Minimum supported client-Windows XPMinimum supported server-Windows Server 2003

Page 151: Team 7

151

GlobalMemoryStatusEx (2/2)GlobalMemoryStatusEx

typedef struct _MEMORYSTATUSEX { DWORD     dwLength; DWORD     dwMemoryLoad; DWORDLONG ullTotalPhys; DWORDLONG ullAvailPhys; DWORDLONG ullTotalPageFile; DWORDLONG ullAvailPageFile; DWORDLONG ullTotalVirtual; DWORDLONG ullAvailVirtual; DWORDLONG ullAvailExtendedVirtual;

} MEMORYSTATUSEX, *LPMEMORYSTATUSEX;

所有的實體記憶體

可用的實體記憶體

所有的 Page File

可用的 Page File

所有的虛擬記憶體可用的虛擬記憶體

擴展的虛擬記憶體

使用記憶體的百分比

Page 152: Team 7

152

Page 153: Team 7

153

GetPerformanceInfo (1/2)

GetPerformanceInfo Struct PERFORMANCE_INFORMATION

Header: Psapi.h

<<use>>

<<contant>><<contant>>

Minimum supported client-Windows XPMinimum supported server-Windows Server 2003

Page 154: Team 7

154

GetPerformanceInfo (2/2)GetPerformanceInfo

typedef struct _PERFORMANCE_INFORMATION { DWORD  cb; SIZE_T CommitTotal; SIZE_T CommitLimit; SIZE_T CommitPeak; SIZE_T PhysicalTotal; SIZE_T PhysicalAvailable; SIZE_T SystemCache; SIZE_T KernelTotal; SIZE_T KernelPaged; SIZE_T KernelNonpaged; SIZE_T PageSize; DWORD  HandleCount; DWORD  ProcessCount; DWORD  ThreadCount;

} PERFORMANCE_INFORMATION, *PPERFORMANCE_INFORMATION;

系統可 commit 的最大 page 數量

系統有多少實體的記憶體以 page計算系統有多少可使用的記憶體以 page計算系統有多少快取記憶體

The sum of the memory currently in the paged and nonpaged kernel pools, in pages.

Page大小 , 以 byte計算Process 數量

系統當下 commit多少 page

執行緒述量

Page 155: Team 7

155

系統記憶體

MemMon

系統記憶體

GetPerFromanceInfo

GlobalMemoryStatusEx

由上述兩個 api 以及 MemMom每秒掃描一次,可以知道總觀性的記憶體使用狀況,以及藉由windows.h 、 psapi.h 所提供的資料結構,可了解更詳細的數值,實作出系統記憶體介面。

Page 156: Team 7

156

MemMon 行程記憶體

Module32First

Module32Next

Heap32First

Heap32Next

Thread32First

Thread32Next

CreateToolhelp32Snapshot

Process32First Process32Next

Page 157: Team 7

157

CreateToolhelp32Snapshot

CreateToolhelp32Snapshot

dwFlags

Header: TlHelp32.h

<<in>><<contant>>

Minimum supported client-Windows XPMinimum supported server-Windows Server 2003

th32ProcessID<<in>>

擷取系統目前部分的狀態

必須為再擷取出的process之一,並且視為此觀察區快中的第一個 process

th32ProcessID

<<out>> 成功則回傳一個open handle失敗回傳 INVALID_HANDLE_VALUE

Page 158: Team 7

158

Overview

Module32First

Module32Next

Heap32First

Heap32Next

Thread32First

Thread32Next

Process32First

Process32Next

CreateToolhelp32Snapshot<<use once>>

struct MODULEENTRY32<<use>>

struct HEAPENTRY32<<use>>

struct THREADENTRY32<<use>>

struct PROCESSNTRY32<<use>>

Header: TlHelp32.h

<<contant>>

Minimum supported client

-Windows XPMinimum supported server

-Windows Server 2003

Page 159: Team 7

159

HEAPENTRY32(2/2)Heap32Next & Heap32First

typedef struct tagHEAPENTRY32 { SIZE_T    dwSize; HANDLE    hHandle; ULONG_PTR dwAddress; SIZE_T    dwBlockSize; DWORD   dwFlags; DWORD     dwLockCount; DWORD     dwResvd; DWORD     th32ProcessID; ULONG_PTR th32HeapID;

} HEAPENTRY32, *PHEAPENTRY32;

指向線性位置的開頭

Process ID

Heap ID

指向 heap block

Page 160: Team 7

160

THREADENTRY32(2/2)Thread32Next & Thread32First

typedef struct tagTHREADENTRY32 { DWORD dwSize; DWORD cntUsage;

DWORD th32ThreadID; DWORD th32OwnerProcessID; LONG  tpBasePri; LONG  tpDeltaPri; DWORD dwFlags;

} THREADENTRY32, *PTHREADENTRY32;

屬於哪個 process ID擁有此Thread

此 Thread 的優先權

Thread ID

Page 161: Team 7

161

MODULEENTRY32Module32Next & Module32First

typedef struct tagMODULEENTRY32 { DWORD   dwSize; DWORD   th32ModuleID; DWORD   th32ProcessID; DWORD   GlblcntUsage; DWORD   ProccntUsage; BYTE    *modBaseAddr; DWORD   modBaseSize; HMODULE hModule; TCHAR   szModule[MAX_MODULE_NAME32 + 1]; TCHAR   szExePath[MAX_PATH]; } MODULEENTRY32, *PMODULEENTRY32;

Process ID

此 module 的起始位置

此 module 有多大

此 module 的名字

此 module 的 path

Module ID

Page 162: Team 7

162

PROCESSENTRY32Process32Next & Process32First

typedef struct tagPROCESSENTRY32 { DWORD     dwSize; DWORD     cntUsage; DWORD     th32ProcessID; ULONG_PTR th32DefaultHeapID; DWORD     th32ModuleID; DWORD     cntThreads; DWORD     th32ParentProcessID; LONG      pcPriClassBase; DWORD     dwFlags; TCHAR     szExeFile[MAX_PATH];

} PROCESSENTRY32, *PPROCESSENTRY32;

Process ID

Module id

此 process 的 parent id

此 process 的名字

此 process擁有幾個執行序

Page 163: Team 7

163

Process id

Module Name

執行緒數量

此 Module 的 path

Page 164: Team 7

164

行程記憶體利用上述的 API ,就可以輕鬆的偵測到目前系統記憶體狀態,在根據每過1秒就掃描一次,就可以做到偵測行程記憶體的資訊。

這樣就可以做到這些介面大部分的資訊了!

Page 165: Team 7

165

2012/6/13

吳彥諄吳政樺

4.8 本章總結

Page 166: Team 7

166

這章讓我們學到:Windows 記憶體管理員的基礎知識

Ex. 如何管理分頁及非分頁記憶體Ex. 如何管理實體記憶體

記憶體管理員如何有效低管理有限資源並降低管理負擔Windows 記憶體管理員的最佳化設施MemMon 的一些實作原理

本章總結