1.66k likes | 1.8k Views
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 平衡集管理員
E N D
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 平衡集管理員 • 4.7 記憶體監視工具 • 4.7.1 記憶體監監視工 • 4.4.4Windows的寫時複製 • 4.8 本章總結 • 4.4 記憶體分頁 • 4.4.3 分頁錯誤處理 • 4.4.4Windows 的寫時複製 • 4.5 實體記憶體管理 • 4.5.1 PFN資料庫 • 4.5.2 實體頁面的狀態變化 • 4.5.3 實體頁面串列的管理和操作 • 4.5.4 修改頁面寫出器 • 4.5.5 行程/堆疊交換器 • 4.5.6 低/高記憶體通知
4.4.3 分頁錯誤處理 2012/6/13 陳嘉浩
Outline • 回顧 • Intel x86 中的 PDE 和 PTE • 無效 PTE 和原型 PTE • 分頁錯誤處理 • 分頁錯誤的類型 • 錯誤檢查的流程 • 錯誤處理的方法
Intel x86 的 PDE 和 PTE 註解 PDE:Page Directory Entry PTE:Page Table Entry
無效 PTE 情形 註解 PFN: Page Frame Number 稍候在 4.5 章將會介紹 要求一個零頁面 位於分頁檔 未知原因錯誤 頁面正在轉移
原型 PTE 介紹 指向原型PTE的無效PTE
原型 PTE 例子 修改自第六組投影片 行程A分頁目錄 行程A分頁表 實體記憶體 記憶體集區的區段物件 行程B分頁目錄 行程B分頁表 無效 分頁檔
行程A分頁目錄 行程A分頁表 實體記憶體 記憶體集區的區段物件 行程B分頁目錄 行程B分頁表 有效 無效 分頁檔 當行程B要存取頁面P2時,它依然會發現自己的PTE是無效的,因此它會檢查原型PTE,並且發現P2已經在實體記憶體中了。接著P2分頁表中的PTE則會重新指向到實體頁面 假設行程A要存取頁面P2,它會發現分頁表中P2的PTE是無效的,但它會指向原型PTE,而原型PTE此時也是無效的且指向分頁檔中的頁面,此時記憶體管理員會根據原型PTE的指示為P2分配一個實體頁面 實體頁面分配完成後,行程A分頁表中的PTE以及原型PTE都會指向該實體分頁,此時行程A分頁表中的PTE以及原型PTE都為有效,而行程B分頁表中的PTE則保持原狀
分頁錯誤種類 • 解決辦法 • 分配一個實體頁面並且從硬碟上讀入內容 • 回傳值 • STATUS_SUCCESS • STATUS_PAGE_FAULT_PAGING_FILE • STATUS_IN_PAGE_ERROR • 無效 PTE • 頁面位於分頁檔或對應檔案中 • 存取一個尚在記憶體中但正在轉移過程中的頁面 • 存取一個尚未提交的頁面 • 存取一個要求零的頁面 • 在使用者模式下存取只能在核心的頁面 • 寫一個唯讀的頁面 • 寫一個防護的頁面 • 執行標記為「不可執行」頁面中的程式碼 • 寫一個標記為「寫時複製」頁面 • 解決辦法 • 申請一個填滿零的頁面,並加入到目前行程的工作集 • 回傳值 • STATUS_SUCCESS • STATUS_PAGE_FAULT_DEMAND_ZERO • STATUS_IN_PAGE_ERROR • 解決辦法 • 複製目前行程私有的頁面,並替換原來的頁面 • 回傳值 • STATUS_SUCCESS • STATUS_PAGE_FAULT_COPY_ON_WRITE • STATUS_IN_PAGE_ERROR • 解決辦法 • 將該頁面轉移回到行程工作集或系統工作集 • 回傳值 • STATUS_SUCCESS • STATUS_PAGE_FAULT_TRANSITIONSTATUS_IN_PAGE_ERROR 回傳值 STATUS_PAGE_FAULT_GUARD_PAGE 回傳值 STATUS_ACCESS_VIOLATION
分頁錯誤檢查流程 –MmAccessFault() 函式 註解 APC:Asynchronous Procedure Call,屬於 IRQL 中斷層級,用於實現延遲和異步的過程調用。詳細請參考第5.2.2節
分頁錯誤檢查流程 – 系統位址空間 位於分頁檔 未知原因錯誤 頁面正在轉移
分頁錯誤處理方法 –MiDispatchFault() 函式 • 原型PTE • 檢查如果原型PTE表示了頁面尚在記憶體中,即原型PTE是有效的,或在轉移狀態,則可以先將原型PTE變成有效,然後設置實際的PTE • 否則,呼叫MiResolveProtoPteFault()函式根據情況進行處理,然後呼叫MiCompleteProtoPteFault()函式把已經有效的原型PTE影響到真正的PTE • 正在轉移的PTE • 要求零頁面的PTE • 在分頁檔中的PTE
分頁錯誤處理方法 –MiDispatchFault() 函式 • 原型PTE • 正在轉移的PTE • 呼叫MiResolveTransitionFault()函式,把正在轉移的頁面從它所在的串列中移除,並重新設置PTE,使它變成一個有效的PTE • 要求零頁面的PTE • 在分頁檔中的PTE
分頁錯誤處理方法 –MiDispatchFault() 函式 • 原型PTE • 正在轉移的PTE • 要求零頁面的PTE • 呼叫MiResolveDemandZeroFault()函式向系統要一個記憶體頁面,然後設置好PFN資料庫中對應該頁面的項目,以及出錯虛擬位址的硬體PTE • 在分頁檔中的PTE
分頁錯誤處理方法 –MiDispatchFault() 函式 • 原型PTE • 正在轉移的PTE • 要求零頁面的PTE • 在分頁檔中的PTE • 呼叫MiResolvePageFileFault()函式將出錯頁面的PTE設置為正在轉移以及讀取操作正在進行。該函式不會發起I/O,而只是填充好這些資訊,放在輸出參數的ReadBlock中 Why?
分頁錯誤處理方法 –MiDispatchFault() 函式 • 各種錯誤的輔助處理函式最後都會回傳結果訊息給MiDispatchFault()函式作後續處理,它會根據回傳的指示決定是否需要呼叫IoPageRead()函式發出I/O請求,並且針對I/O成功與否作相關的處理。最後,MiDispatchFault()也會負責釋放資源以及維護鎖的一致性
小結 • 在本章節裡面,我們探討了: • 有哪些可能導致分頁錯誤的情形 • MmAccessFault() 函式如何透過剖析 PDE 和 PTE 判斷分頁錯誤屬於哪一種情形 • MiDispatchFault() 函式如何針對各種分頁錯誤情形進行處理
4.4.4 Windows的寫時複製 2012/6/13 郭星辰 姜智文
Windows的寫時複製(copy-on-write) • 現代作業系統的一個重要特性 • 機制 • 父行程、子行程為獨立的分頁表,但分頁表指向相同的實體頁面(唯讀) • 當行程寫數據,記憶體管理員複製頁面,父行程、子行程擁有私有頁面(可讀寫)
寫時複製的優點 • 將複製的動作延遲到真正需要兩個行程分配各自私有頁面的時候,避免不必要的資料複製,減緩了對記憶體的需求
實作原理 • 記憶體區段物件創建函數NtCreateSection和MmCreateSection參數SectionPageProtection指定了記憶體區段物件中頁面的保護屬性 • PAGE_READ (讀) • PAGE_READWRITE (完全共用,只有一個) • PAGE_WRITECOPY (寫時複製)
建立記憶體區段物件 保護屬性由MmCreateSection參數SectionPageProtection經MiMakeProtectionMask函式變化而來,PAGE_WRITECOPY變為MM_WRITECOPY 分頁檔支撐的記憶體集區 MiCreatePagingFileMap 映像檔記憶體集區 MiCreateImageFileMap 資料檔案記憶體集區 MiCreateDataFileMap NtCreateSection 此函式建立的映像檔記憶體區預設情形皆為寫時複製的,除非SECTION有特別設定不相容的保護屬性 MmCreateSection 頁面保護屬性為MM_EXECUTE_READWRITE,可讀寫、可執行、不可寫時複製 MiSectionInitialization 建立實體記憶體區物件
PTE 分頁表項目 • PTE資料結構MMPTE_HARDWARE中,第9位元是一個保留位元,Windows將他解釋成CopyOnWrite位元
實作過程 (1/2) • 階段一: 一個寫時複製的頁面被第一次分配 • 第一次存取頁面時,硬體PTE無效 • MiCompleteProtoPteFault呼叫巨集來 填充PTE的位元 • 定義中,寫時複製保護屬性為0x200,即PTE中的第9位元 設置為1,而寫位元(第1位元)設置0,發生分頁錯誤
實作過程 (2/2) • 階段二:一個行程對一個支援寫時複製的頁面執行了寫入操作,觸發一個分頁錯誤 • MmAccessFault檢測錯誤 → 呼叫MiCopyOnWrite 1. 根據參數中指定的出錯位址找到PFN資料庫中對應的項,印證他是一個原型PTE 2. 透過MiRemoveAnyPage申請一個實體頁面 3. 呼叫MiInitializeCopyOnWritePfn初始化其PFN對應的項 4. 從系統PTE區域中申請一個空閒PTE,完成記憶體頁面的複製 5. 填好出錯位址PTE項目 6. 舊頁面PFN資料庫中計數減一
4.5.1 PFN 資料庫 2012/6/13 黃詩蘋 姜智文
PFN 資料庫 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; 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
~問題來囉~ 請問實體頁面的狀態有哪些呢? 請列出五種來吧ˊ_>ˋ
MMPFN資料結構 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; 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; (d)轉移狀態的PFN項目 (a)活動狀態頁面的PFN項目 (b)備用狀態或已修改狀態的PFN項目 (c)歸零的或空閒頁面的PFN項目
MMPFNENTRY 定義 typedefstruct _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 ; 頁面已被修改 正進行”讀取”或”寫入”操作 原型PTE 頁面狀態
4.5.2 實體頁面的狀態變化 2012/6/13 余修丞 姜智文
頁面的調度與使用 • 記憶體管理員根據「系統記憶體的數量」以及各個「行程對於記憶體的需求」,動態調度實體頁面的使用 • ex: 當一行程需要記憶體,記憶體管理員可以從「零化串列」或「空閒串列」中找到頁面滿足行程需求 • 行程結束,記憶體管理員回收行程的頁面
實體頁面的狀態轉移 • 記憶體管理員動態調度的過程,頁面可能會經歷各種變化 修改串列 修剪”髒”頁面 工作集 (行程或系統) “軟”錯誤 修改頁面 寫出器 “軟”錯誤 刪除頁面 “軟”錯誤 備用串列 修剪乾淨頁面 “硬”錯誤 空閒串列 歸零串列 必要時 零頁面程序
實體頁面的狀態轉移 • 記憶體管理員動態調度的過程,頁面可能會經歷各種變化 修改串列 修剪”髒”頁面 工作集 (行程或系統) “軟”錯誤 修改頁面 寫出器 “軟”錯誤 刪除頁面 “軟”錯誤 備用串列 修剪乾淨頁面 “硬”錯誤 空閒串列 歸零串列 必要時 零頁面程序
行程取得頁面 -以分頁錯誤為例-1 • 為解決分頁錯誤,行程會需要一個頁面,它有可能從圖中的4個串列其中之一取得實體記憶體頁面 歸零串列 空閒串列 備用串列 修改串列
行程取得頁面 -以分頁錯誤為例-2 • 從修改或備用串列中取得實體頁面分頁錯誤由正在轉移狀態的無效PTE引起 實體頁面 PFN資料庫項目 1.尋找 PTE 分頁框架編號 2.呼叫 3. 該頁面從 串列中移除 備用串列 修改串列 MiUnlinkPageFromList函式
行程取得頁面 -以分頁錯誤為例-3 • 從空閒(零化或備用)串列取得實體頁面:分頁錯誤由一位於分頁檔中的PTE所引起,分頁錯誤處理常式會透過MiRemoveAnyPage函式獲得一實體頁面滿足分頁錯誤。 • 從零化(空閒或備用)串列取得實體頁面:若分頁錯誤需要零頁面來滿足此錯誤,則呼叫MiRemoveZeroPage函式獲得一零化頁面
實體頁面的狀態轉移 • 記憶體管理員動態調度的過程,頁面可能會經歷各種變化 修改串列 修剪”髒”頁面 工作集 (行程或系統) “軟”錯誤 修改頁面 寫出器 “軟”錯誤 刪除頁面 “軟”錯誤 備用串列 修剪乾淨頁面 “硬”錯誤 空閒串列 歸零串列 必要時 零頁面程序
頁面於串列間的轉移 (1/3) • 空閒串列 -(零頁面緒程)-> 零化串列-MmZeroPageThread函式
零頁面緒程 (1/2) • MmZeroPageThread函式是個無限迴圈,他等待以下兩個事件之一:MmZeroingPageEvent和PoSystemIdelTimer MiInsertPageInFreeList函式 MmZeroPageThread 1.插入頁面 2. 空閒串列頁面數大於 MmMinimumFreePageToZero =8 3. 通知 零化事件 MmZeroingPageEvent 空閒串列
零頁面緒程 (2/2) • 零化操作 重複以上步驟,直至目前空閒串列頁面全部零化 零化事件 MmZeroingPageEvent MmZeroPageThread 1.通知 2. 取得頁面 設定成壞頁面 指定為零 3. 呼叫 4. 將頁面插入至 空閒串列 MmZeroPageListHead MiInsertPageInList 函式
實體頁面的狀態轉移 • 記憶體管理員動態調度的過程,頁面可能會經歷各種變化 修改串列 修剪”髒”頁面 工作集 (行程或系統) “軟”錯誤 修改頁面 寫出器 “軟”錯誤 刪除頁面 “軟”錯誤 備用串列 修剪乾淨頁面 “硬”錯誤 空閒串列 歸零串列 必要時 零頁面程序
頁面於串列間的轉移 (2/3) • 備用串列-(必要時)->空閒串列一般情況下,備用串列頁面不會主動地轉移到空閒串列中,除非這些頁面已經確定不被使用了。 • 發生轉移的例子:當行程刪除一段記憶體時,包括行程、程序結束時清除記憶體做的操作 (發生在MiDeleteVirtualAddresses函式中)
從工作集「刪除頁面」 • MiDeleteVirtualAddresses函式被呼叫到,會把不再共用的有效頁面轉移到空閒串列中,也就是從工作集刪除頁面,見圖4.29 • 此過程發生如下: MiDeleteVirtualAddresses 函式 轉移頁面 工作集 空閒串列 共用計數器減1為0 引用計數器為1 1. 呼叫 MiDecrementShareCount函式 MiDeletePte 函式 共用計數器 引用計數器 2. 呼叫