當前位置:
首頁 > 新聞 > 深入理解Windows頁幀號(一)

深入理解Windows頁幀號(一)

Windows頁幀號(Page Frame NuMer ,PFN)介紹

Windows以及幾乎所有操作系統都會使用PFN資料庫 ( PFN DataBase ) ,以便跟蹤虛擬分配的頁面,進一步管理哪些頁面要被寫入或移出,哪些頁面需要緩存頁面等。

虛擬分配頁面的管理過程都是通過一個名為頁幀號(PFN)的列表進行管理的,關於每個物理和虛擬分配頁面的狀態及其相應屬性都有一長串解釋。

本文,我將通過大量實際的案例,來解釋Windows PFN的實現。

如果你熟悉non-PAE模式和PAE模式系統,那麼就應該注意到,在non-PAE模式下,每個PFN結構需要24個位元組,而在PAE模式系統中,需要25個位元組,因此如果你的頁面是4096個位元組,那麼就分配大約24個位元組以保持對每個頁面的追蹤。

在non-PAE模式下,每個物理頁大小是4K,對於每一個物理頁,PFN資料庫會使用一個24位元組長的結構來保存它的相關信息,比如該物理頁是否已經被使用,這是170:1的比率。而在PAE模式下,每個物理頁大小是4K,對於每一個物理頁,PFN資料庫會使用一個28位元組長的結構來保存它的相關信息,這是146:1的比率。這意味著PFN資料庫中,每1G大小的物理內存,都需要大約6M或7M來描述其中的信息。但是如果你有一個具有16G物理內存的32位系統,那麼它只需要大約112M的2G內核虛擬地址空間來處理隨機存取存儲器(RAM)。這也是為什麼擁有16G或更大物理內存的系統不允許使用3G模式(也稱為expaneuserva)的原因,因為該模式會將用戶虛擬地址空間增加到3G並將32位系統的內核虛擬地址空間減少到1G,擴展頁面的好處之一(例如每頁2M)需要更少的MMPFN結構。

在開始深入了解PFN之前,請記住術語「Page」主要用於操作系統級概念,而「Frame」用於CPU級概念,因此「Page」表示虛擬頁面,「Page Frame」表示物理頁面。

PFN列表

PFN由描述某些頁面狀態的列表組成,比如活動列表(Active List)顯示活動頁面(例如,在working sets中);待機列表(Standby List)表示先前在磁碟中備份的列表,頁面本身可以在不產生磁碟IO的情況下清空和重用;修改列表(Modified List )顯示該頁面先前已被修改,並且必須以某種方式寫入磁碟;移出列表(Freed List),顧名思義,它顯示不再需要維護的頁面,可以被移出;最後是零列表(Zero List),描述一個包含全零(0)的頁面。

下圖顯示了PFN資料庫列表之間的相互關聯關係:

這些列表是用於管理內存中「頁面錯誤」狀態的,每次發生「頁面錯誤」後,Windows都試圖找到一個可用的表單頁,如果列表為空則是零列表,然後零列表則從移出列表中獲取可用的表單頁,另外,如果移出列表也為空,則移出列表從待機列表獲取可用的表單頁,並將頁面用全零(0)表示。

零頁面線程

在Windows中,有一個優先順序為0的線程,負責在系統空閑時將內存歸零,並且是整個系統中唯一優先順序為0的線程。這是可用的最低優先順序,因為用戶線程至少是1,該線程儘可能清除移出列表。此外,Windows中有一個名為RtlSecureZeroMemory()的函數,它可以安全地移出一個位置,但是在以下的內核透視圖中,nt!KeZeroPages負責移出頁面。

下圖顯示了零頁面線程的整個過程:

此時,零線程(Zero Thread)就可以看得清清楚楚。知道它來自系統進程,且它的優先順序為0,這應該就足夠了,不再需要更多的信息了。首先嘗試查找系統的nt!_eprocess:

!process 0 System

現在我們可以看到系統的線程,我的目標線程(零線程)的細節如下:

THREAD ffffd4056ed00040 Cid 0004.0040 Teb: 0000000000000000 Win32Thread: 0000000000000000 WAIT: (WrFreePage) KernelMode Non-Alertable

fffff8034637f148 NotificationEvent

fffff80346380480 NotificationEvent

Not impersonating

DeviceMap ffff99832ae1b010

Owning Process ffffd4056ec56040 Image: System

Attached Process N/A Image: N/A

Wait Start TickCount 4910 Ticks: 4 (0:00:00:00.062)

Context Switch Count 21023 IdealProcessor: 3

UserTime 00:00:00.000

KernelTime 00:00:01.109

Win32 Start Address nt!MiZeroPageThread (0xfffff80346144ed0)

Stack Init ffffe700b7c14c90 Current ffffe700b7c14570

Base ffffe700b7c15000 Limit ffffe700b7c0f000 Call 0000000000000000

Priority 0 BasePriority 0 PriorityDecrement 0 IoPriority 2 PagePriority 5

Child-SP RetAddr Call Site

ffffe700`b7c145b0 fffff803`46016f8a nt!KiSwapContext+0x76

ffffe700`b7c146f0 fffff803`46016951 nt!KiSwapThread+0x16a

ffffe700`b7c147a0 fffff803`46014ba7 nt!KiCommitThreadWait+0x101

ffffe700`b7c14840 fffff803`461450b7 nt!KeWaitForMultipleObjects+0x217

ffffe700`b7c14920 fffff803`460bba37 nt!MiZeroPageThread+0x1e7

ffffe700`b7c14c10 fffff803`46173456 nt!PspSystemThreadStartup+0x47

ffffe700`b7c14c60 00000000`00000000 nt!KiStartSystemThread+0x16

正如你所看到的,它的起始地址是nt!MiZeroPageThread,且它的優先順序是0,如果你看到調用棧,那麼就可以看到之前調用的 nt!MiZeroPageThread。

更多細節,請訪問《隱藏的內存分配成本》一文。

PFN的Windows結構是nt!_MMPFN,如下圖所示:

如你所見,_MMPFN需要28個位元組。

PFN記錄會根據其物理地址順序存儲在存儲器中,這意味著你可以在PFN的幫助下計算出物理地址。

Physical Address = PFN * page size(e.g 4096 Byte) + offset

PFN資料庫的地址位於nt!MmPfnDatabase,你可以使用以下所示的代碼段在Windbg中獲取PFN資料庫地址。

2: kd> x nt!MmPfnDatabase

fffff800`a2a76048 nt!MmPfnDatabase =

!memusage

windbg中另一個非常有用的命令是!memusage,這個命令幾乎提供了內存布局中關於PFN和頁面的幾乎所有內容及其相關細節,例如文件、字體、系統驅動程序、DLL模塊、可執行文件(包括它們的名稱和它們的分頁位修改) 。

!memusage命令從物理內存角度顯示內存統計信息,無數個頁面信息將被列印出來,可以說是「最內存」的信息。此命令會查看所有的頁幀,所以運行時會非常的耗時。

該命令的簡要介紹如下所示:

2: kd> !memusage

loading PFN database

loading (100% complete)

Compiling memory usage data (99% Complete).

Zeroed: 9841 ( 39364 kb)

Free: 113298 ( 453192 kb)

Standby: 105520 ( 422080 kb)

Modified: 7923 ( 31692 kb)

ModifiedNoWrite: 0 ( 0 kb)

Active/Valid: 286963 ( 1147852 kb)

Transition: 45 ( 180 kb)

SLIST/Bad: 567 ( 2268 kb)

Unknown: 0 ( 0 kb)

TOTAL: 524157 ( 2096628 kb)

Dangling Yes Commit: 140 ( 560 kb)

Dangling No Commit: 37589 ( 150356 kb)

Building kernel map

Finished building kernel map

(Master1 0 for 80)

(Master1 0 for 580)

(Master1 0 for 800)

(Master1 0 for 980)

Scanning PFN database - (97% complete)

(Master1 0 for 7d100)

Scanning PFN database - (100% complete)

Usage Summary (in Kb):

Control Valid Standby Dirty Shared Locked PageTables name

ffffffffd 11288 0 0 0 11288 0 AWE

ffffd4056ec4c460 0 112 0 0 0 0 mapped_file( LeelUIsl.ttf )

ffffd4056ec4c8f0 0 160 0 0 0 0 mapped_file( malgun.ttf )

ffffd4056ec4d6b0 0 108 0 0 0 0 mapped_file( framd.ttf )

.....

ffffd4057034ecd0 328 148 0 0 0 0 mapped_file( usbport.sys )

ffffd4057034f0e0 48 28 0 0 0 0 mapped_file( mouclass.sys )

ffffd4057034f7d0 32 28 0 0 0 0 mapped_file( serenum.sys )

ffffd405703521a0 0 20 0 0 0 0 mapped_file( swenum.sys )

.....

-------- 0 20 0 ----- ----- 0 session 0 0

-------- 4 0 0 ----- ----- 0 session 0 ffffe700b8b45000

-------- 4 0 0 ----- ----- 0 session 1 ffffe700b8ead000

-------- 32520 0 84 ----- ----- 1324 process ( System ) ffffd4056ec56040

-------- 2676 0 0 ----- ----- 304 process ( msdtc.exe ) ffffd405717567c0

-------- 4444 0 0 ----- ----- 368 process ( WmiPrvSE.exe ) ffffd405718057c0

-------- 37756 0 60 ----- ----- 1028 process ( SearchUI.exe ) ffffd405718e87c0

.....

-------- 8 0 0 ----- 0 ----- driver ( condrv.sys )

-------- 8 0 0 ----- 0 ----- driver ( WdNisDrv.sys )

-------- 52 0 0 ----- 0 ----- driver ( peauth.sys )

-------- 24744 0 0 ----- 0 ----- ( PFN Database )

Summary 1147852 422260 31692 129996 204428 25156 Total

.....

b45b 64 0 0 60 0 0 Page File Section

b56b 4 0 0 4 0 0 Page File Section

b7ec 84 0 0 64 0 0 Page File Section

b905 12 0 0 0 0 0 Page File Section

bf5c 4 0 0 0 0 0 Page File Section

.....

有關這些頁面的更多信息,Windbg幫助文檔是這樣解釋的:

你可以使用!vm擴展命令分析虛擬內存使用情況,這個擴展通常比!memusage更有用。有關內存管理的更多信息,請參閱Mark Russinovich和David Solomon撰寫的Microsoft Windows Internals。!pfn擴展命令可用於在PFN資料庫中顯示特定頁幀條目。

在下一節,我會介紹如何更詳細的查看這些命令。


喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 嘶吼RoarTalk 的精彩文章:

通過電子郵件遠程獲取NTLM哈希
狩獵俄羅斯APT28——對其一系列新的惡意軟體分析

TAG:嘶吼RoarTalk |