windbg下看系統非分頁記憶體

2021-07-26 08:33:40 字數 3208 閱讀 7021

這篇文章實在是閒的無聊才寫的,因為快過年了...文章基於xpsp3

先看看和非分頁記憶體相關的全域性變數,也好有個大局觀:

kd> x nt!mmnonpaged*

805517d8 nt!mmnonpagedpoolend = 8055af84 nt!mmnonpagedpoolend0 = 8055af80 nt!mmnonpagedpoolexpansionstart = 8055fb20 nt!mmnonpagedsystemstart = 8055af60 nt!mmnonpagedpoolfreelisthead = 8055ae38 nt!mmnonpagedpoolstart = kd> dd nt!mmnonpagedpoolstart l1

8055ae38 8164b000

kd> dd nt!mmnonpagedpoolend0 l1

8055af84 86800000

nt!mmnonpagedpoolend0:儲存基本nonpagedd記憶體池的結束位址

nt!mmnonpagedsystemstart:儲存基本nonpagedd記憶體池的開始位址

nt!mmnonpagedpoolfreelisthead:空閒nonpaged頁面佇列頭陣列;xp下該陣列有4個元素,每個陣列元素都是_list_entry結構。mmnonpagedpoolfreelisthead[0]中的節點包含1個頁面;mmnonpagedpoolfreelisthead[1]中的節點儲存了2個頁面,以此類推。

來看下這幾個佇列的使用情況:

kd> dd nt!mmnonpagedpoolfreelisthead l8 ;下面的是我自己加的,用於分割各個_list_entry結構

8055af60 [8055af60 8055af60] [86674000 863e9000]

8055af70 [86071000 86071000] [863ec000 8164b000]

從dd的結果可以看出,現在陣列元素0和2是空佇列,裡面的空閒頁面已被瓜分完。也就是單頁面和3頁面的nonpaged記憶體池已用完。現在我們知道nonpaged記憶體池的使用情況,再來看看各個空閒頁面鍊錶中的節點。既然mmnonpagedpoolfreelisthead[0]和mmnonpagedpoolfreelisthead[2]已經告罄,我們就來看看剩下的兩個鍊錶:

kd> dt nt!*mmfree*

ntoskrnl!_mmfree_pool_entry

kd> dt ntoskrnl!_mmfree_pool_entry

+0x000 list : _list_entry

+0x008 size : uint4b

+0x00c signature : uint4b

+0x010 owner : ptr32 _mmfree_pool_entry

上面的結構是空閒頁面佇列中各個節點的型別。以mmnonpagedpoolfreelisthead[1]中的節點為例,每個節點中包含2個連續的頁面,每個頁面的起始位置被用作ntoskrnl!_mmfree_pool_entry結構。再繼續下去前,先讓我介紹一下各個域的作用:

1.只有節點中的第乙個頁面的ntoskrnl!_mmfree_pool_entry!_list_entry域會被加入到mmnonpagedpoolfreelisthead[1]所在的空閒頁面鍊錶中,第二個頁面的ntoskrnl!_mmfree_pool_entry!_list_entry域不起作用;

2.由於節點中的兩個頁面的位址是連續的,因此,在mmnonpagedpoolfreelisthead[1]中定位到第乙個頁面的ntoskrnl!_mmfree_pool_entry!_list_entry域,再加上page_size,就可以獲得後續頁面。至於ntoskrnl!_mmfree_pool_entry!size的作用,則用於反應節點中有多少個頁面;

3.除了節點中第乙個頁面的ntoskrnl!_mmfree_pool_entry!owner域指向本頁面的ntoskrnl!_mmfree_pool_entry以外,節點中的其他頁面的owner域都指向第乙個頁面的ntoskrnl!_mmfree_pool_entry。

了解了這個背景後,看下mmnonpagedpoolfreelisthead[1]中的節點的值:

kd> dt _list_entry 8055af60+8 ;mmnonpagedpoolfreelisthead[1]的位址

nt!_list_entry

[ 0x86674000 - 0x863e9000 ]

+0x000 flink : 0x86674000 _list_entry [ 0x863c8000 - 0x8055af68 ] ;記憶體0x86674000處有乙個_mmfree_pool_entry型別的節點

+0x004 blink : 0x863e9000 _list_entry [ 0x8055af68 - 0x86197000 ]

kd> dt ntoskrnl!_mmfree_pool_entry 0x86674000

+0x000 list : _list_entry [ 0x863c8000 - 0x8055af68 ]

+0x008 size : 2 ;節點中有2個頁面

+0x00c signature : 2

+0x010 owner : 0x86674000 _mmfree_pool_entry ;owner指向自己

kd> dt ntoskrnl!_mmfree_pool_entry 0x86674000+0x1000 ;節點中的第二個頁面

+0x000 list : _list_entry [ 0x44524352 - 0x90028 ]

+0x008 size : 0x35e41f0

+0x00c signature : 0

+0x010 owner : 0x86674000 _mmfree_pool_entry ;owner指向前乙個頁面的_mmfree_pool_entry結構

windows就是基於這樣的結構,對nonpaged記憶體池進行管理的~

分頁記憶體,非分頁記憶體

分頁記憶體是低中斷級別的例程可以訪問的。而非分頁記憶體則是各個中斷級別的例程都可以使用的。區別在於 分頁記憶體是虛擬記憶體,在物理上未必總是能得到。作業系統實現虛擬記憶體的主要方法就是通過分頁機制。在win32中,實體地址空間,二維虛擬位址空間和實際記憶體位址是三個不同的概念。作業系統通過段選擇子構...

分頁記憶體和非分頁記憶體區別

在寫驅動的時候,經常要呼叫exallocatepoolwithtag函式分配記憶體,其中第乙個引數可以是如下幾個 nonpagedpool 從非分頁記憶體池中分配記憶體 pagedpool 從分頁記憶體池中分配記憶體 nonpagedpoolmustsucceed 從非分頁記憶體池中分配記憶體,如果...

何謂可分頁和非分頁記憶體

何謂可分頁和非分頁記憶體 預設情況下,核心載入器會載入所有的 部分和全域性資料到非分頁記憶體中。而且,載入器是一次載入整個驅動的可執行檔案,包括相關的dll。載入後,核心載入器關閉驅動程式檔案,甚至你可以刪除當前正在執行的驅動檔案。但是,你可以告訴載入器你希望驅動的哪部分是可分頁,所謂可分頁,就是可...