Transcript 4.4 記憶體分頁
Team 6
Modern Operating System Kernels
Final Report
975002025
975002018
975002503
975002050
975002525
975002024
975002040
100522007
100522086
100522022
100522061
林彥宇
李韋成
游惇雅
林俊伸
莊欣瑜
沈宗弦
謝宛儀
楊睿豪
陸俊廷
張哲嘉
徐千惠
1
CONTENTS
(page 217 ~ page 256)
Chapter 4 Windows 記憶體管理
4.2 Windows系統記憶體管理
4.2.2 系統位址空間記憶體管理
4.2.3 系統PTE區域的管理
4.3 行程記憶體管理
4.3.1 位址空間的建立和初始化
4.3.2 位址空間切換
4.3.3 行程位址空間的記憶體管理
4.3.4 記憶體區段物件
4.4 記憶體分頁
4.4.1 Intel x86中的PTE
4.4.2 軟體PTE: 無效PTE和原型PTE
2
4.2 WINDOWS系統記憶體管理
4.2.2 系統位址空間記憶體管理
4.2 Windows系統記憶體管理
4.2.1 系統位址空間初始化
4.2.2 系統位址空間記憶體管理
4.2.3 系統PTE區域的管理
975002503 游惇雅
975002025 林彥宇
975002018 李韋成
3
(三) 執行體記憶體集區的管裡演算法
執行體記憶體集區
(非分頁)
系統非分頁
集區
非分頁集區
擴充區域
執行體記憶體集區
(分頁)
系統分頁
集區
系統PTE
集區
4
POOL_DESCRIPTOR
執行體記憶體集區物件是由資料結構POOL_DESCRIPTOR描述
5
全域變數
.
6
初始化
. MiInitializeNonPagedPool
系統非分頁集區初始化
PFN資料庫初始化
InitializePool(NonPagedPool,0)
執行體非分頁集區初始化
MiBuildPagedPool
系統分頁集區初始化
InitializePool(PagedPool,0L)
執行體分頁集區初始化
7
基本演算法
若一次記憶體分配的大小超過
POOL_BUDDY_MAX,則執行體記憶體集區直
接呼叫底層的系統記憶體集區來申請足夠的頁面。
否則,ExAllocatePoolWithTag函式檢查記憶體
集區內部的lookaside list,以期望可找到合適
大小的空閒區塊,若未能找到滿足條件的區塊,
則向系統記憶體集區申請一個新的頁面,把頁面
的一部份傳給客戶,剩下的加入到適當大小的
lookaside list中。
8
管理結構
PoolType
PoolIndex
.
.
ListHeads陣列:
[0]
[1]
[2]
8位元組區塊
[3]
16位元組區塊
8位元組區塊
16位元組區塊
…
[511]
4080位元組區塊
4080位元組區塊
9
頁面內部結構
0
PI
BS PT Tag
PS PI
使用者資料
BS PT Tag
PS PI
使用者資料
BS PT Tag
使用者資料
PS:PreviousSize
PI:PoolIndex
BS:BlockSize
PT:PoolType
10
ExAllocatePoolWithTag (1/2)
.
.
11
ExAllocatePoolWithTag (2/2)
Step 1
◦ 若NumberOfBytes > POOL_BUDDY_MAX則呼
叫MiAllocatePoolPages(),否則就直接使用
lookaside來分配。
Step 2
◦ 確 定 POOL_DESCRIPTOR 物 件 PoolDesc 和 索 引
ListNumber後,使用do迴圈搜尋滿足條件的空閒
區塊。
Step 3
◦ 執行完Step 2仍未找到有效區塊的話,則呼叫
MiAllocatePoolPages函式來向系統記憶體集區申
請一個新的頁面。
12
ExFreePoolWithTag (1/6)
.
Step 1
◦ ExAllocatePoolWithTag 透過
POOL_BUDDY_MAX呼叫
MiAllocatePoolWithTag函式進行配置,相對地,
再釋出空間亦呼叫MiFreePoolWithTag.
13
ExFreePoolWithTag (2/6)
Step 2
◦ 根據參數P,找到相關的POOL_HEADER,置於區
域變數Entry中,並檢查期中的成員資訊,進一步找
到它後面的區塊的POOL_HEADER,檢查後面區塊
的PreviousSize和目前區塊的BlockSize是否相同。
Step 3(小區塊釋放)
◦ 在ExAllocatePoolWithTag 中,配置小區塊即從
Lookaside List中提取適當區塊。相對地,在
ExFreePoolWithTag中,若Lookaside List未達到
預定深度,則將釋出的區塊放入Lookaside List中
※分頁及非分頁集區lookaside list:PPPagedLookasideList & PPNPagedLookasideList
14
ExFreePoolWithTag (3/6)
Step 4-1 (merge)
15
ExFreePoolWithTag (4/6)
Step 4-2 (merge)
16
ExFreePoolWithTag (5/6)
Step 4-3 (merge)
17
ExFreePoolWithTag (6/6)
Step 4-4
(merge)
18
4.2 WINDOWS系統記憶體管理
4.2.3 系統PTE區域的管理
4.2 Windows系統記憶體管理
4.2.1 系統位址空間初始化
4.2.2 系統位址空間記憶體管理
4.2.3 系統PTE區域的管理
19
4.2.3 系統PTE區域的管理
執行體記憶體集區
(非分頁)
系統非分頁
集區
非分頁集區
擴充區域
執行體記憶體集區
(分頁)
系統分頁
集區
系統PTE
集區
20
_MMPTE_LIST
空閒頁面的PTE沒有對應的實體頁面
21
PTE串列 & PTE cluster
PTE cluster(2 PTE)
NextEntry … 0 0
2
… 0 0
xx
… x x
xx
… x x
xx
… x x
PTE cluster(1 PTE)
NextEntry … 1 0
PTE cluster(3 PTE)
NextEntry … 0 0
3
… 0 0
0
… 0 0
22
全域變數
.
23
主要程式碼中之函式
MiInitializeSystemPtes
MiReserveSystemPtes
MiReleaseSystemPtes
24
MiInitializeSystemPtes (1/2)
本函式目的:執行PTE區域的初始化
Step 1: 在系統非分頁集區的初始化完成後,呼叫本函式執行
PTE區域的初始化
Step 2: 設定起始PTE和結束PTE的位址
Step 3: 將這段PTE全部歸零
本函式也初始化單串列
Step 1: 每個節點是一塊記憶體,稱作Chunk(分為五種大
小:1.2.4.8.16),MilnitializeSystemPtes函式中有個區域陣列
Lists定義了每種chunk的數量
Step 2: chunk 從系統非分頁集區中分配,加入到
MiSystemPteSListHead定義的單串列中
Step 3: 利用此單串列來初始化MiSystemPteNBHead
25
MiInitializeSystemPtes (2/2)
i = MM_SYS_PTE_TABLES_MAX;
do{
I -= 1;
do{
Lists[i] -=1;
MiReleaseSystemPtes(PointerPte,
MmSysPteIndex[i],
SystemPteSpace);
PointerPte +=MmSysPteIndex[i];
}while(Lists[i] !=0);
}while(i!=0);
26
MiReserveSystemPtes (1/2)
本函式目的:分配非分頁頁面
含有兩個參數
NumberOfPtes
頁面的數量
SystemPtePoolTyoe
僅有兩種可能,SystemPteSpace或
NonPagedPoolExpansion,這裡只考慮
SystemPteSpace
根據NumberOfPtes確認應該使用哪種大小的佇列
如果能從中提取一個節點,直接將之中的起始PTE回
傳給Client.
如果此種大小的區塊數量小於預定的最小數,則呼叫
MiFeedSysPtePool函式,以獲得更多此種大小的區
塊。
27
MiReserveSystemPtes (2/2)
本函式目的:釋放PTE
Step 1: 本函式的參數指定了要釋放的PTE位置和個數
及類型,而在呼叫此函式之前,指定範圍的PTE必須是
無效的。
Step 2: 將這些PTE全部歸零
如果帶釋放的數量小於等於16,考慮把這段PTE範圍插入
MiSystemPtesNBHead所指的佇列中,而不直接回收到空閒
的PTE串列。
若插入不成功或數量超過16則歸還到PTE串列中
從第一個空閒的PTE開始,即是MmFirstFreeSystemPte陣列的
元素,找到第一個NextEntry欄位超過目前起始PTE的空閒磁簇。
考慮能否跟他合併成一個更大的磁簇,如果此空閒磁簇恰好緊
貼要釋放的範圍則合併。
若不能合併則插入一個新的空間磁簇在他的後面。
28
4.3 行程記憶體管理
4.3.1位址空間的建立和初始化
4.3 行程記憶體管理
4.3.1 位址空間的建立和初始化
4.3.2 位址空間切換
4.3.3 行程位址空間的記憶體管理
4.3.4 記憶體區段物件
975002024 沈宗弦
29
4.3.1位址空間的建立和初始化
0x00000000
~
行程位置空間
4GB
0x7 f f f f f f f
0x80000000
~
系統位置空間
0xf f f f f f f f
行程虛擬位置空間
30
4.3.1位址空間的建立和初始化
PspCreateProcess建立行程時,若指定的
Parent行程不為NULL
MmCreateProcessAddressSpace
PspCreateProcess
建立一個新的位址空間
MmInitializeProcessAddressSpace
初始化行程位址空間
31
建立行程位址空間
呼叫MmCreateProcessAddressSpace函式
建立位址空間
(base/ntos/mm/procx86.c 28-362)
BOOLEAN
MmCreateProcessAddressSpace (
IN ULONG MinimumWorkingSetSize,
//建立行程的最小工作集的大小
IN PEPROCESS NewProcess,
//建立行程的行程物件
OUT PULONG_PTR DirectoryTableBase
//指向行程位址空間的分頁目錄位址
)
32
建立行程位址空間 ─ 函式流程
1.
呼叫MiChargeCommitment確保系
統有足夠的分頁業檔空間。
在intel x86,需要4個頁面
33
建立行程位址空間 ─ 函式流程
2.
確認目前實體頁面是否達到
MinimumWorkingSetSize指定的要求
3.
申請一個實體頁面作為分頁目錄頁面
實
體
頁
面
分頁目錄頁面
將分頁框架編號存至
區域變數PageDirectoryIndex中
34
建立行程位址空間 ─ 函式流程
4.
實
體
頁
面
申請一個超空間分頁表頁面
將分頁框架編號存至
區域變數HyperSpaceIndex中
超空間分頁表頁面
什麼是超空間:
這是一個特別的區域,可以用來對應
處理程序工作組清單,也可以暫時地
對應其他的實體分頁,以便進行諸如
零位調整可用清單上的分頁(在零位
清單是空的,但需要使用零位分頁的
時候)、使其他分頁表中的分頁表輸
入失效(例如當某個分頁從待命清單
中移除時),以及關於建立處理程序、
設定新處理程序的位址空間等作業。※1
35
建立行程位址空間 ─ 函式流程
5.
申請一個VAD點陣圖
實
體
頁
面
VAD點陣圖
將分頁框架編號存至
區域變數VadBitMapPage中
VAD點陣圖請參考4.3.3之介紹
36
建立行程位址空間 ─ 函式流程
6.
申請一個實體頁面當作工作集串列
實
體
頁
面
7.
工作集串列
初始化EPROCESS 中的
Vm.MinimumWorkingSetSize ,Workin
gSetPage ,DirectoryTableBase 欄位
37
建立行程位址空間 ─ 函式流程
8.
初始化超空間分頁表頁面
(base/ntos/mm/procx86.c
229-262)
.
.
.
超空間分頁表頁面
一個PTE
.
.
.
系統PTE區
VAD點陣圖
工作集串列
分別填寫完對應的VAD點陣圖與工作集串列的分頁表項目,
完成後釋放此PTE。
38
建立行程位址空間 ─ 函式流程
在PFN資料庫中設置分頁目錄頁面的PTE
位置(虛擬位址0xc0300000)
10. 把新行程加入到系統內部維護行程串列
中
9.
.
.
.
MmProcessLinks
.
.
.
MmProcessList
插入串列中
EPROCESS
39
建立行程位址空間 ─ 函式流程
11. 初始化分頁目錄頁面
(base\ntos\mm\i386\procx86.c第294~353行)
0xc000000
0
.
.
.
分頁目錄頁面
一個PTE
.
.
.
系統PTE(動作
完成後釋放)
之後把4個頁面的負擔紀
錄至MmProcessCommit
中
(全域變數)
0xc400000
0
複製系統空間的PDE
(0x80000000開始的位置範圍)
PDE
超空間分頁表頁面
(內涵VAD及工作集)
行程位置空間
0x80000000
系統位置空間
0xf f f f f f f40f
建立行程位址空間 ─ 函式流程
12. 呼叫MiSessionAddProcess函式把新行
程加入到新行程的父行程所在的工作階
段空間,即MmSessionSpace中。
MiSessionAddProcess
更新工作階段空間中的行程計數器,以及將新行程加
入工作階段空間維護的行程串列中。
41
4.3.1位址空間的建立和初始化
MmCreateProcessAddressSpace
PspCreateProcess
建立一個新的位址空間
MmInitializeProcessAddressSpac
初始化行程位址空間
42
4.3.1位址空間的建立和初始化
MmInitializeProcessAddressSpace
函式在以下四種情況會被呼叫
建立新使用者行程時,SectionToMap有效、
ProcessToClone為NULL.
建立新使用者行程時,沒有記憶體區段物件,
類似fork( )操作。
建立新系統行程時, SectionToMap、
ProcessToClone皆為NULL、相關旗標亦為關
閉時。
系統初始化時,Parent為NULL時。
43
初始化行程位址空間
接著呼叫MmInitializeProcessAddressSpace
初始化使用者空間部分(0x0-0x7fffffff)
NTSTSTUS
MmInitializeProcessAddressSpace (
IN PEPROCESS ProcessToInitialize ,
//要初始化的目標行程
IN PEPROCESS ProcessToClone OPTIONAL ,
//新行程的位址空間可從該行程複製獲得
IN PVOID SectionToMap OPTIONAL ,
//提供一記憶體區段物件,鰾是在新行程位址空間中對應此物件
IN OUT PULONG CreateFlags ,
//各種與行程建立相關的旗標
OUT POBJECT_NAME_INFORMATION *AuditName
OPTIONAL ,
//物件名稱資訊指標
);
44
初始化行程位址空間 - 函式流程
1.
2.
3.
判斷是否更新新行程空間中的系統PDE (分頁後半
部分),若需要則呼叫MiUpdateSystemPdes.
呼叫KeAttachProcess, 把目前緒程”暫時”附加
至待初始化的行程物件上。
標明目前正在使用位址空間2.
ProcessToInitialize->Flags = PS_PROCESS_FLAGS_ADDRESS_SPACE2
4.
初始化位址建立鎖及工作集互斥器
ProcessToInitialize->AddressCreationLock
ProcessToInitialize->Vm.WorkingSetMutex
45
初始化行程位址空間 - 函式流程
5.
初始化VAD樹並設置最後修剪時間及工
作集串列
Vm.LastTrimTime
Vm.VmWorkingSetList
6.
7.
8.
初始化新行程分頁目錄和超空間分頁表
的PNF,以及VAD點陣圖和工作集的PNF.
初始化新行程工作集串列。
MiInitializeWorkingSetList
若以3GB啟動方式或64位元系統,則需
另外建立一VAD,來保留共用的使用者
頁面。
46
初始化行程位址空間 - 函式流程
略過
10.根據系統登錄設置及目前系統環境,
來確定是否在新行程中由高向低分配
虛擬位址空間。
9.
47
初始化行程位址空間 - 函式流程
11.建立新行程
EPROCESS
.
.
.
ImageFileName
.
.
.
MmMapViewOfSection 參閱4.3.4
1
(新行程同樣對應) 2
SectionToMap 記憶體區段物件的可執行映像檔
4
(ntdll.dll對應至新行程位址空間) 3
PsMapSystemDll
(把新行程的虛擬位址空間插入工作管理串列)
5 MiAllowWorkingSetExpansion
48
初始化行程位址空間 - 函式流程
12. 行程複製
檢查目前行程每一個VAD,且根據頁面屬性檢
查PTE,並複製到新行程,其複製特性見4.4.4
父行程呼叫MiCloneProcessAddressSpace
複製位址空間後,把新行程虛擬空
間位址插入到工作管理集串列中。
MiAllowWorkingSetExpansion
13. 如果是系統行程則什麼也不做
14. 如果新行程是一個複製的行程或系統行程,
則關閉大頁面建立旗標,結束函式。
(PROCESS_CREATE_FLAGS_LARGE_PAGES)
49
4.3.1位址空間的建立和初始化
經過兩個步驟的建立後,一個行程的空
間位址已經初步建立起來。
MmCreateProcessAddressSpace
PspCreateProcess
建立一個新的位址空間
MmInitializeProcessAddressSpace
初始化行程位址空間
50
4.3 行程記憶體管理
4.3.2 位址空間切換
4.3 行程記憶體管理
4.3.1 位址空間的建立和初始化
4.3.2 位址空間切換
4.3.3 行程位址空間的記憶體管理
4.3.4 記憶體區段物件
975002040 謝宛儀
51
分頁目錄
0x00000000 – 0x7fffffff
前半
每個process私有
完全轉移到新行程的位址空間
0x80000000 – 0xffffffff
後半
每個process共有,但分頁目錄頁面為獨立的。
新位址空間中的PDE項目指向全域的分頁表
52
系統位址空間的記憶體配置結構
0x80000000
MmPfnDatabase
核心、HAL等系統模組的
映象區
分頁表是否 頁面是否
已分配
已分配
√
√
√
√
MmNonPagedPoolStart
非分頁集區
√
√
MiSystemCacheStartExtra
系統快取額外區
MiSystemCacheSizeExtra(個頁面)
√
╳
系統PTE額外區
√
╳
工作階段管理員、
MiSystemViewStart
系統檢視
╳
╳
Windows子系統
MmSessionBase
工作階段空間
╳
╳
0xc0000000
分頁表
√
√
0xc0400000
超空間和行程工作集
√
╳
可能在不同行程的分頁目錄中
MmSystemCacheWorkingSetList(0xc0c00000)
系統快取結構 有不同的檢視
√
╳
MmPagedCacheStart(0xc1000000)
系統快取
√
╳
MmPagedPoolStart
分頁集區
╳
╳
MmNonPagedPoolExpansionStart
系統PTE區域
√
╳
非分頁集區擴充區
√
╳
0xffbe0000
當機轉存區
√
╳
保留區
√
╳
53
0xffffffff
PFN 資料庫
4.3.2 位址空間切換
新行程有可能指向錯誤的分頁集區,產生分
頁錯誤。
利用延遲計算(lazy evaluation)來保持分頁集
區分頁表對應的一致性
◎MmSystemPagePtes記錄了分頁集區的分頁表對應
在行程切換前後,新老行程的工作集串列和
VAD點陣圖所對應的PDE指向各自的超空間
分頁表頁面。
◎MmWorkingSetList為目前行程的工作集串列
54
4.3.2 位址空間切換
Windows行程切換實作
只需切換分頁目錄頁面,即CR3暫存器。
無須對分頁目錄中的PDE做任何調整或一
致性維護。
系統空間中除了超空間和工作階段空間部
分以外,在新老行程中保持一致。
55
4.3 行程記憶體管理
4.3.3 行程位址空間的記憶體管理
4.3 行程記憶體管理
4.3.1 位址空間的建立和初始化
4.3.2 位址空間切換
4.3.3 行程位址空間的記憶體管理
4.3.4 記憶體區段物件
975002050 林俊伸
56
4.3.3 行程位址空間的記憶體管理
使用者模式只能使用 0x0 – 7fffffff的記憶體
位址
保留一段記憶體,
但不真正使用。
實際使用記憶體
使用者程式必須經過以下兩步驟才能使用
◦ (1)Reserve
(2)Commit
實際可提交的量 = 全部實體記憶體 + 分頁檔 – 系統使用記憶體
57
4.3.3 行程位址空間的記憶體管理
VirtualAlloc
空閒
VirtualAllocEx
保留
VirtualFreeEx
Virtuallock
提交
VirtualFree
VirtualUnlock
58
4.3.3 行程位址空間的記憶體管理
上
層
VirtualFree
VirtualFree
Ex
VirtualAlloc
VirtualAllocEx
實
作
NtAllocateVirtualMemory
NtFreeVirtualMemory
下
層
59
4.3.3 行程位址空間的記憶體管理
Window的行程位址透過VAD管理
VAD初始化
MmInitializeProcessAd
dressSpace
EPROCESS物件
VadRoot欄位
VADRoot類型
MM_AVL_TABLE
typedef struct _MM_AVL_TABLE {
MMADDRESS_NODE
BalancedRoot;
ULONG_PTR DepthOfTree: 5;
ULONG_PRT Unused: 3;
ULONG_PRT
NumberGenericTableElements: 24;
VAD
PVOID NodeHint; 樹根
PVOID NodeFreeHint;
} MM_AVL_TABLE,
*PMM_AVL_TABLE;
60
VAD樹中節點型別 (1/2)
typedef struct _MM_MMADDRESS_NODE {
維護AVL
union {
樹本身
LONG_PTR Balance : 2;
struct _MMVAD * parent;
}
struct _MMVAD * LeftChild;
struct _MMVAD * RightChild;
ULONG_PTR StartingVpn;
ULONG_PTR EndingVpn;
} MMADDRESS_NODE,
*PMMADDRESS_NODE;
61
VAD樹中節點型別 (2/2)
typedefstruct
struct _MMVAD {
typedef
union {
_MM_MMADDRESS_NODE
{
LONG_PTR
Balance : 2;
union
{
struct
_MMVAD
* parent;
LONG_PTR
Balance
: 2;
} struct _MMVAD * parent;
struct
_MMVAD * LeftChild;
}
struct _MMVAD * RightChild;
LeftChild;
ULONG_PTR
StartingVpn;
struct _MMVAD
* RightChild;
ULONG_PTR EndingVpn;
StartingVpn;
} MMADDRESS_NODE,
ULONG_PTR EndingVpn;
*PMMADDRESS_NODE;
} MMADDRESS_NODE,
…
*PMMADDRESS_NODE;
範圍
樹真正結點類型為
MMVAD
62
VadRoot.BalancedRoot.RightChild
VAD樹
[10, 10]
左子點
[20, 20]
[130,134]
[270, 2a3]
[300,305]
Root
[240,24f]
[2b0, 2f0]
[320, 322]
右子點
[67000, 6700e]
[77e40, 77f41]
[7ffb0, 7ffd3]
[410,50f]
[77c50,77cee]
[7c800, 7c8bf]
[7ffdd, 7ffde]
一個實際行程的VAD樹
提交or保留
[30, 13f]
[140,23f]
[250,265]
[310,31f]
[330,33f]
[510,56f]
[77f50,77feb]
[7f6f0,7f7ef]
[7ffdb,7ffdb]
[7ffdc,7ffdc]
[7ffde,7ffde]
63
TABLE SEARCH_RESULT
MiFindNodeOrparent )
IN PMM_AVL_TABLE Table,
IN ULONG_PTR StartingVpn,
OUT PMMADDRESS_NODe
*NodeOrParent
);
AVL 實作: Base\ntos\mm\addrsup.c
MiFindNodeOrParent ()
MiInsertNode()
MiRemoveNode()
VOID
FASTCALL
MiInsertNode (
IN PMMADDRESS_NODE
NodeToInsert,
IN PMM_AVL_TABLE Table
);
VOID
FASTCALL
MiInsertNode (
IN PMMADDRESS_NODE
NodeDelete,
IN PMM_AVL_TABLE Table
);
64
MiFindNodeOrParent ()
TABLE SEARCH_RESULT
MiFindNodeOrparent )
尋找這點父節
點orAVL節點
IN PMM_AVL_TABLE Table,
IN ULONG_PTR StartingVpn,
OUT PMMADDRESS_NODe
*NodeOrParent
);
65
MiInsertNode() & MiRemoveNode()
VOID
FASTCALL
MiInsertNode (
IN PMMADDRESS_NODE
NodeToInsert,
IN PMM_AVL_TABLE Table
);
VOID
FASTCALL
MiInsertNode (
IN PMMADDRESS_NODE
NodeDelete,
IN PMM_AVL_TABLE Table
);
66
VAD點陣圖
找尋位置
是否保留
或提交
找尋連續
的空閒位
址範圍
位元表示64k記憶體是否出現在VAD樹中
VAD樹
找尋連續空
閒位元
VAD點
陣圖
67
VAD點陣圖相關函式
MiInsertVadCharges()
MiInsertVadCharges()StartBit =
(ULONG)
(((ULONG)MI_64K_ALIGN
(MI_VPN_TO_VA(Vad>StartingVpn)))/X64K);
EndBit =
(ULONG)
(((ULONG)MI_64K_ALIGN
(MI_VPN_TO_VA(Vad>EndingVpn)))/X64K);
MiReturnPageTablePateCommitment()
MiFindEmptyAddressRange()
VadBitMap.SizeOfBitMap =
MiLastMadBit + 1;
BadBitMap.Buffer =
VAD_BITMAP_SPACE;
RtlSetBits (&VadBitMap,
StartBit, EndBit – StartBit +
1);
68
4.3 行程記憶體管理
4.3.4 記憶體區段物件 (1/2)
4.3 行程記憶體管理
4.3.1 位址空間的建立和初始化
4.3.2 位址空間切換
4.3.3 行程位址空間的記憶體管理
4.3.4 記憶體區段物件
975002040 謝宛儀
69
4.3.4 記憶體區段物件
是windows平台上兩個或多個行程之間共用記
憶體的一種常用方法
實體儲存資源
直接以操作記憶體的方式存取檔案
建立行程
位址空間
可
執
行
檔
映
像
記憶體區段物件
70
物件主體定義
(base\ntos\mm\mi.h)
// 記憶體區的VAD節點
// 指向一個區段物件
// 記憶體區的大小
// 包含記憶體區的一組旗標
// 指定記憶體區中頁面的保護屬性
71
4.3.4 記憶體區段物件
分兩種
分頁檔支撐的記憶體區(page file backed
section), 也稱為檔案對應物件(file
mapping object).
檔案支撐的記憶體區段(file backed
section)
記憶體區段的建立
由MmCreateSection函式來完成的
(base\ntos\mm\creasect.c 402-1611行)
72
記憶體區段的建立 (1/8)
(base\ntos\mm\creasect.c)
73
記憶體區段的建立 (2/8)
(base\ntos\mm\creasect.c)
分頁檔支撐的記憶體區(page file backed
section)也稱為檔案對應物件(file mapping
object).
指定記憶體區的大小
空
74
記憶體區段的建立 (3/8)
(base\ntos\mm\creasect.c)
檔案支撐的記憶體區段(file backed section)
指定了記憶體區
最大可被擴充或對應的大小
非空
75
記憶體區段的建立 (4/8)
(base\ntos\mm\creasect.c)
指定記憶體區中
每個頁面的保護旗標
76
記憶體區段的建立 (5/8)
(base\ntos\mm\creasect.c)
指定記憶體區段物件中
:
記憶體區段的分配方式
SEC_BASED
SEC_RESERVE
SEC_COMMIT SEC_IMAGE
SEC_FILE
SEC_LARGE_PAGES
指定記憶體區中
每個頁面的保護旗標
77
記憶體區段的建立 (6/8)
(base\ntos\mm\creasect.c)
指定記憶體區段物件中
記憶體區段的分配方式
SEC_BASED
SEC_RESERVE
SEC_COMMIT SEC_IMAGE
SEC_FILE
指定了物件管理員所要的資訊,
SEC_LARGE_PAGES
包括物件名、安全描述項等等。
78
記憶體區段的建立 (7/8)
(base\ntos\mm\creasect.c)
記憶體區段物件未命名以致不能共用
記憶體區的頁面
為私有頁面
指定了物件管理員所要的資訊,
包括物件名、安全描述項等等。
79
記憶體區段的建立 (8/8)
(base\ntos\mm\creasect.c)
指定存取方式:
EXECUTE、READ、
WRITE
80
MmCreateSection函式的程式碼邏輯
②
①
③
(1/3)
填充
區段
SEGMENT
ControlAre
a
MmCreateSection
分頁檔支撐的記憶體集區
控制區
檔案物件
MiCreatePagingFileMap
CONTROL_AREA
FILE_OBJECT
SectionObjectPoin
Segment
映像檔記憶體集區
ter
FilePointer
MiCreateImageFileMap
SUBSECTION
有對應的
子記憶體區段
檔案物件
SUBSECTION
資料檔案記憶體集區
子記憶體區段
有任一個為非空
MiCreateDataFileMap
……
81
MmCreateSection函式的程式碼邏輯
②
①
MmCreateSection
(2/3)
分頁檔支撐的記憶體集區
MiCreatePagingFileMap
映像檔記憶體集區
MiCreateImageFileMap
資料檔案記憶體集區
空
MiCreateDataFileMap
有對應的
檔案物件
82
MmCreateSection函式的程式碼邏輯
(3/3)
(base\ntos\mm\creasect.c)
83
記憶體區段物件與其他物件的關聯結構 (1/3)
記憶體區段
物件
Segment
區段
SEGMENT
ControlArea
控制區
CONTROL_AREA
Segment
FilePointer
SUBSECTION
子記憶體區段
SUBSECTION
子記憶體區段
虛擬位址描述項
MMVAD
ControlArea
……
記憶體區段物件指標
SECTION_OBJECT_POITERS
DataSectionObject
ImageSectionObject
檔案物件
FILE_OBJECT
SectionObjectPoin
ter
84
記憶體區段物件與其他物件的關聯結構 (2/3)
區段物件本身是在分頁集區中分配的,並且有一指
標指向一個控制區物件,用於描述此區段內頁面對
應的原型PTE陣列等資訊。
控制區物件(CONTROL_AREA結構)是在非分頁
集區分配的,它有一個指標指向區段物件,維護
反映了與之關聯的記憶體區段物件被對應了多少次
I/O操作所必要的資訊。
控制區
CONTROL_AREA
區段
SEGMENT
ControlArea
Segment
FilePointer
SUBSECTION
子記憶體區段
SUBSECTION
子記憶體區段
……
檔案物件
FILE_OBJECT
SectionObjectPoint
er
85
記憶體區段物件與其他物件的關聯結構 (3/3)
檔案物件是Windows I/O和儲存系統中的一
個核心物件,也是記憶體管理子系統與I/O子
系統打交道的重要途徑。
控制區
CONTROL_AREA
Segment
FilePointer
SUBSECTION
子記憶體區段
SUBSECTION
子記憶體區段
……
檔案物件
FILE_OBJECT
SectionObjectPointer
記憶體區段物件指標
SECTION_OBJECT_POINTERS
DataSectionObject
ImageSectionObject
86
4.3 行程記憶體管理
4.3.4 記憶體區段物件 (2/2)
4.3 行程記憶體管理
4.3.1 位址空間的建立和初始化
4.3.2 位址空間切換
4.3.3 行程位址空間的記憶體管理
4.3.4 記憶體區段物件
975002525 莊欣瑜
87
建立區段(SEGMENT)物件 (1/2)
NtCreateSection
MmCreateSection
分頁檔支撐的記憶體集區
MiCreatePagingFileMap
映像檔記憶體集區
MiCreateImageFileMap
資料檔案記憶體集區
MiCreateDataFileMap
有對應的
檔案物件
88
建立區段(SEGMENT)物件 (2/2)
89
建立記憶體區段物件
NtCreateSection
MmCreateSection
分頁檔支撐的記憶體集區
MiCreatePagingFileMap
映像檔記憶體集區
MiCreateImageFileMap
資料檔案記憶體集區
MiCreateDataFileMap
90
分頁檔支撐的記憶體區段物件 (1/4)
MiCreatePagingFileMap
確定所需
memory大小
ExAllocatePoolWithTag
申請記憶體
初始化區段物件
中的成員
申請CONTROL_AREA
物件
初始化
CONTROL_AREA和
子記憶體區的成員
91
分頁檔支撐的記憶體區段物件 (2/4)
NtMapViewOfSection
MmMapViewOfSection
分頁檔支撐的記憶體集區
MiMapViewOfDataSection
映像檔記憶體集區
MiMapViewOfImageSection
資料檔案記憶體集區
MiMapViewOfDataSection
實體記憶體區
MiMapViewOfPhysicalSection
92
分頁檔支撐的記憶體區段物件 (3/4)
NtMapViewOfSection
MmMapViewOfSection
分頁檔支撐的記憶體集區
MiMapViewOfDataSection
映像檔記憶體集區
MiMapViewOfImageSection
資料檔案記憶體集區
MiMapViewOfDataSection
實體記憶體區
MiMapViewOfPhysicalSection
93
分頁檔支撐的記憶體區段物件 (4/4)
MiMapViewOfDataSection
呼叫
MiFindEmptyAddressRangeDown
或MiFindEmptyAddressRange確定
行程的位址空間範圍
範圍內的PTE
設置成區段物
件的
SegmentPte
Template值
把VAD物件
插入目標行
程的VAD樹
中
申請VAD物
件、初始化
讓VAD物件的
ControlArea指向記憶體
區的控制區物件
94
可執行映像檔的記憶體區段物件
NtCreateSection
MmCreateSection
(1/5)
分頁檔支撐的記憶體集區
MiCreatePagingFileMap
映像檔記憶體集區
MiCreateImageFileMap
資料檔案記憶體集區
MiCreateDataFileMap
95
可執行映像檔的記憶體區段物件
(2/5)
MiCreateImageFileMap
從映像檔讀取標頭資訊
利用標頭中的資訊填充
控制區和區段物件中各
個成員
在非分頁集區建立一個
控制區物件; 在分頁集
區建立一區段物件
Note:
• 子記憶體區段物件的數量與映
像檔中區域(SECTION)數量相
等
• 子記憶體區有自己的保護屬性、
原型PTE、在磁碟上的位置
96
可執行映像檔的記憶體區段物件
(3/5)
MiInsertImageSectionObject
記憶體區段
物件
Segment
區段
SEGMENT
ControlArea
控制區
CONTROL_AREA
Segment
FilePointer
SUBSECTION
子記憶體區段
SUBSECTION
子記憶體區段
虛擬位址描述項
MMVAD
ControlArea
……
記憶體區段物件指標
SECTION_OBJECT_POITERS
DataSectionObject
ImageSectionObject
檔案物件
FILE_OBJECT
SectionObjectPoin
ter
97
可執行映像檔的記憶體區段物件
NtMapViewOfSection
(4/5)
分頁檔支撐的記憶體集區
MiMapViewOfDataSection
映像檔記憶體集區
MiMapViewOfImageSection
MmMapViewOfSection
資料檔案記憶體集區
MiMapViewOfDataSection
實體記憶體區
MiMapViewOfPhysicalSection
98
可執行映像檔的記憶體區段物件
(5/5)
MiMapViewOfImageSection
確定目標虛
建立VAD節
擬位址
點物件
把VAD物件
插入到行程
的VAD樹中
由參數CapturedBase指定
由記憶體區段物件的區段物件的
BasedAddress成員決定
呼叫MiFindEmptyAddressRangeDown
或MiFineEmptyAddressRange
99
資料檔案的記憶體區段物件 (1/4)
NtCreateSection
MmCreateSection
分頁檔支撐的記憶體集區
MiCreatePagingFileMap
映像檔記憶體集區
MiCreateImageFileMap
資料檔案記憶體集區
MiCreateDataFileMap
10
0
資料檔案的記憶體區段物件 (2/4)
建立一個控制區物件,存在在File Object的
SectionObjectPointer的
DataSectionObject成員中
確定記憶體區大小
呼叫
MiCreateDataFileMap
函式
在分頁集區中申請一區段物件
控制區的子記憶體區從一個擴充到多個
把原檔案打散成大小為
MmallocationFragment的一組
chunk
MiCreateDataFileMap初始
化控制區物件和區段物件
10
1
資料檔案的記憶體區段物件 (3/4)
NtMapViewOfSection
MmMapViewOfSection
分頁檔支撐的記憶體集區
MiMapViewOfDataSection
映像檔記憶體集區
MiMapViewOfImageSection
資料檔案記憶體集區
MiMapViewOfDataSection
實體記憶體區
MiMapViewOfPhysicalSection
10
2
資料檔案的記憶體區段物件 (4/4)
MiMapViewOfDataSection
確定目標虛
建立VAD節
擬位址
點物件
把VAD物件
插入到行程
的VAD樹中
由參數CapturedBase指定
由記憶體區段物件的區段物件的
BasedAddress成員決定
呼叫MiFindEmptyAddressRangeDown或
MiFineEmptyAddressRange
10
3
特殊記憶體區段物件 (1/4)
\\Device\\PhysicalMemory
系統初始化階段由MiSectionInitialization函
式直接建立
沒有呼叫MmCreateSection函式
可用於直接把實體記憶體對應到行程位址空
間中
10
4
特殊記憶體區段物件 (2/4)
\\Device\\PhysicalMemory
NtMapViewOfSection
分頁檔支撐的記憶體集區
MiMapViewOfDataSection
映像檔記憶體集區
MiMapViewOfImageSection
MmMapViewOfSection
資料檔案記憶體集區
MiMapViewOfDataSection
實體記憶體區
MiMapViewOfPhysicalSection
10
5
特殊記憶體區段物件 (3/4)
\\Device\\PhysicalMemory
以SectionOffset和
CapturedViewSize
兩個參數決定對應範
圍
設置虛擬位
址範圍中的
維護行程
分頁目錄項
內部的資
目和分頁表
料結構
項目
10
6
特殊記憶體區段物件 (4/4)
\\Device\\PhysicalMemory
解除對應
呼叫NtUnmapViewOfSection系統服務
MiUnmapViewOfSection函式
根據給定的基底位址找到VAD節點
從VAD樹中移除節點
呼叫MiRemoveMappedView函式
來解除對應
10
7
4.4 記憶體分頁
100522007 楊睿豪
100522086 陸俊廷
10
8
Paging
分頁錯誤
Kernel Trap
Handler
PTE
Memory Manager
的Page Fault
Handler(MmAcces
allocate sFault)解決
Valid Bit= 0
PTE
Valid Bit = 1
虛擬位址
轉譯成實
體位址
But實體記
憶體有限,
當Process
變多時會有
耗光的問題
一般來說,只要
這個Page Fault
合理(EX: 該頁面
已被Swap Out到
外部記憶體),則
Page Fault
Handler會分配實
體頁面,
並設置好PTE。
現今的作業系統大多都提供
Paging功能,將某些頁面
Swap Out到磁碟中儲存,以
空出實體頁面來。
(Windows系統支援一到多個
Page Files,來存放被交換頁面
的內容。)
10
9
4.4 記憶體分頁
4.4.1 INTEL X86中的PTE
4.4 記憶體分頁
4.4.1 Intel x86中的PTE
4.4.2 軟體PTE: 無效PTE和原型PTE
4.4.3 分頁錯誤處理
4.4.4 Windows的寫時複製
11
0
Intel x86的硬體PTE
寫
保留
全域
大頁面
髒
存取過
禁止存取
直接寫
模式
寫
有效
PTE(分頁目錄項目)
PDE(分頁表項目)
PDE與PTE使用相同格式,
唯一區別只在,第七位
元L位元僅對PDE有效
分頁框架編號
(20位元)
31
U
R
R
12 11 10 9
僅適用於多
處理器系統
G
8
L
7
僅適用
於PDE
D
6
A
Cd
Wt
U/S
W
5
4
3
2
1
V
0
必須為1
111
PTE 狀態位元含義
位元
名稱
說明
V
有效
此虛擬頁面是否對應到一個實體頁面
W
寫
在單一處理器上指明可讀寫或唯讀;在多處理器上指明是否可寫。
U/S 模式位元 核心模式程式碼才可存取(0)或使用者模式程式碼可存取(1)
W 1: 可寫 (實做COPY-ON-WRITE)。0: 唯讀。
Wt
直接寫
Write-through / write-back 策略
U/S 1: 只有核心模式程式碼可存取,0: 使用者/核心模式程式碼皆可存取。
Cd
禁止快取 該頁面禁止快取
A
存取過
頁面已經被存取過 (讀取或寫入)
D
髒
頁面已經被寫過
A 當頁面第一次被存取(讀/寫),A位元一定被設定。
L
大頁面
這是一個大頁面PDE,該位元對於PTE無用。
D 當頁面第一次被寫,D位元會被設定。
G
全域
此PTE適用於所有的行程
U
G TLB可幫助快速轉譯虛擬位址。1:
PTE仍有效,TLB設為有效;0: 說明可讀寫或唯讀。
PTE無效,TLB
寫
由軟體控制的位元,此位元僅適用於多處理器系統,
設為無效。
U 用於多處理系統,說明一個頁面已經被另一個處理器寫過。
112
硬體 PTE 定義
Base\ntos\mm\i386\mi386.h
11
3
4.4 記憶體分頁
4.4.2 軟體PTE: 無效PTE和原型PTE
4.4 記憶體分頁
4.4.1 Intel x86中的PTE
4.4.2 軟體PTE: 無效PTE和原型PTE
4.4.3 分頁錯誤處理
4.4.4 Windows的寫時複製
11
4
無效PTE和原型PTE
分頁錯誤
PTE
Valid bit = 0
Kernel Trap
Handler
Memory Manager
的Page Fault
Handler(MmAcces
分派 sFault)解決
所以,PTE中的
其他位元是由作
業系統解譯的。
正是因為有了這一層的靈活性,Windows可以在這樣
的PTE中承載一些資訊,以便實作頁面的管理功能。
11
5
導致 page fault 的原因
補充資料
Fault理由
結果
嘗試讀寫一個不在記憶體內,但是在磁碟上的分
頁檔或記憶體映射檔上的page
配置實體page,從磁碟載入對應的
page並放到相應的working set內
嘗試讀寫一個位於待命或以修改清單內的page
將page交給對應的process、session
或系統working set
嘗試讀寫一個為committed的page
違反操作限制
從user mode中嘗試讀寫只允許kernel
mode使用的page
違反操作限制
嘗試寫入唯讀page
違反操作限制
嘗試讀寫demand-zero page
將填滿0的page加入對應的working
set
寫入copy-on-write page
建立process私有的page複本,換掉
process或系統working set原本的
page
寫入有效但尚未寫回後援儲存裝置的page
設定PTE的Dirty bit
嘗試執行標記為防止執行的page
違反操作限制
嘗試寫入guard page
違反guardpage操作限制
116
4.4 記憶體分頁
4.4.2 軟體PTE: 無效PTE和原型PTE
11
7
無效PTE
Invalid PTE
在Windows中,無效的PTE共有四種情況
1.
2.
3.
4.
In Page File (位於分頁檔中)
Demand Zero Page (要求零頁面)
Page Transition (頁面正在轉移)
Unknown (未知)
11
8
無效PTE
Case1: In Page File
31
12 11 10 9
Page File Offset
0
Transition Bit
Page File
0
(位於分頁檔)
5 4
Protection
Prototype Bit
1
Page File Number
0
0
Valid Bit
所要求的Page位於Page File當中。
這會引發載入Page File的動作
119
無效PTE
Case2: Demand Zero
Page File Offset
31
12 11 10 9
0
0
Transition Bit
零頁面
0
5 4
Protection
Prototype Bit
1
0
0
0
Valid Bit
頁面尚未分配,待下次存取時請
求一個zero page.
120
無效PTE
Case3: Page Transition
31
12 11 10 9
5 4
Page Frame Number 1 0 Protection Cd
Transition Bit
page
Prototype Bit
3
Wt
2
U/S
1
W
0
0
Valid Bit
頁面還在記憶體中,但在換出的過程中,
位於系統的某個實體頁面串列中。
121
無效PTE
Case4: Unknown
為一個全零的PTE
31
12 11 10 9
0
0
Transition Bit
0
5 4
0
Prototype Bit
必須檢查VAD
1
0
0
0
Valid Bit
PTE是0或是Page Table還不存在。這兩
種情況都代表需要去檢查VADs來判斷虛
擬位址是否已經committed。如果是的話,
就建立Page Table來代表所committed的
位址空間。
122
無效PTE
無效 PTE 定義
12
3
4.4 記憶體分頁
4.4.2 軟體PTE: 無效PTE和原型PTE
12
4
原型PTE
原型PTE
如果Page可以在兩個Processes之間共享
的話,Memory Manager會使用名為
Prototype Page Table Entries (PTEs)的
結構來映射這些可能被共享的Pages。
12
5
原型PTE
原型PTE (cont.)
對於以Page
File後援的sections而言,會在
最初建立Section Objects的時候建立
Prototype PTEs陣列。
對於檔案映射而言,會在映射每個view的時
候視需要建立陣列。這些Prototype PTEs屬
於segment結構的一部分。
12
6
原型PTE
原型PTE: Shared Page
memory manager會
使 用 Prototype PTE
的結構來映射這些可
能會被共享的pages
若Page可共享
Shared
Pages
process
first
process
page table
PTE
原型PTE
process
page
(映射到 section
object view)
memory manager
當process首次取用一個映射到
section object view 的 page
時,memory manager會使用原
型PTE的資訊填寫真正用來轉譯
位址的PTE
原型PTE
Info
memory manager
12
7
原型PTE
原型PTE: Shared Page失效
page
(共享)
生效
失效
process
page
table
PTE
實體page
(有資料)
特殊PTE
原型PTE
128
原型PTE
原型 PTE 定義
12
9
原型PTE
當Shared Pages失效時,硬體PTE直接
指向原型PTE。
31
11 10
Prototype PTE Address
1
(7-27Bits)
9
0
8
7
1
Prototype PTE (0-6Bits)
Prototype Bit
0
0
Valid Bit
指向原型 PTE的無效PTE
130
硬體PTE指向原型PTE
13
1
原型PTE
CASE 1 : Active
寫
保留
全域
大頁面
髒
存取過
禁止存取
直接寫
模式
寫
有效
分頁框架編號
(20位元)
31
12
U
R
R
11 10 9
G
8
L
7
D
6
A
Cd
Wt
U/S
W
5
4
3
2
1
V
0
Page位於實體記憶體內,因為先前有Process存取過它
132
原型PTE
CASE 2 : Page File
31
12 11 10 9
Page File Offset
0
Transition Bit
0
5
Protection
4
1
Page File Number
Prototype Bit
0
0
Valid Bit
Page位於Page File內
133
原型PTE
CASE 3: Mapped File
31
12 11 10 9
Mapping File
Offset
0
Transition Bit
0
5
Protection
4
1
Page File Number
Prototype Bit
0
0
Valid Bit
第13~21位元為Mapping file中的偏移量
Page位於映射檔內
134
原型PTE
CASE 4: Demand Zero
31
12 11 10 9
0
0
Transition Bit
0
5
4
Protection
Prototype Bit
1
0
0
0
Valid Bit
頁面尚未分配,待下次存取時請求一個zero page
135
原型PTE
CASE 5: Transition
31
12 11 10 9
Page Frame Number
1
Transition Bit
0
5 4
Protection
Prototype Bit
Cd
3
2
1
0
Wt
U/S
W
0
Valid Bit
頁面在memory中,已被轉移到某實體頁面串列中,可透過
查詢PFN獲知確切狀況。
136
原型PTE
CASE 6: Modified No-Write
31
12 11 10 9
Page Frame Number
1
Transition Bit
0
5 4
Protection
Prototype Bit
Cd
3
2
1
0
Wt
U/S
W
0
Valid Bit
頁面在實體記憶體中,已被修改過,但修改頁面寫出器不會
將其寫回磁碟中。
137
原型PTE
C union - MMPTE 定義
13
8
原型PTE
原型PTE Example
行程A分頁目錄
PDEA_1
行程A分頁表
實體記憶體
PTE_1
PTE_2
行程B分頁目錄
PDEB_1
記憶體集區的區段物件
區段物件結構
原型PTE
行程B分頁表
頁面
頁面P1
P1
頁面P2
P1(有效)
P2( 有效
無效 )
分頁檔
PTE_1
PTE_2
完成
頁面
P2
139
Reference
1)
什麼是超空間
http://support.microsoft.com/kb/294418/zh-tw
2)
VirtualFree
http://msdn.microsoft.com/enus/library/windows/desktop/aa366892(v=vs.85).aspx
3)
VirtualFreeEx
http://msdn.microsoft.com/enus/library/windows/desktop/aa366894(v=vs.85).aspx
4)
VirtualAlloc function
http://msdn.microsoft.com/enus/library/windows/desktop/aa366887(v=vs.85).aspx
5)
作者:Mark E. Russinovich and David A. Solomon with Alex lonescu
譯者:鄧瑋敦, “深入Windows核心:Windows Internals(第五版)”
出版社:博碩
14
0
Q&A
141
Q:
WINDOWS在PROCESS ADDRESS
SPACE MANAGEMENT當中,是用
VAD來管理的。那我們要如何在VAD
樹當中尋找連續的ADDRESS SPACE?
14
2
A:
由於VAD BITMAP中的每一個位元是
代表著64KB記憶體是否出現在VAD
TREE中。因此,想要找到
CONTINUOUS FREE ADDRESSES,
可以透過在VAD BITMAP中搜尋連續
的空閒旗標位元即可。
14
3
The End
Thank you for your listening!
14
4