這篇文章實在是閒的無聊才寫的,因為快過年了...文章基於xpsp3
先看看和非分頁記憶體相關的全域性變數,也好有個大局觀:
從dd的結果可以看出,現在陣列元素0和2是空佇列,裡面的空閒頁面已被瓜分完。也就是單頁面和3頁面的nonpaged記憶體池已用完。現在我們知道nonpaged記憶體池的使用情況,再來看看各個空閒頁面鍊錶中的節點。既然mmnonpagedpoolfreelisthead[0]和mmnonpagedpoolfreelisthead[2]已經告罄,我們就來看看剩下的兩個鍊錶: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]
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。載入後,核心載入器關閉驅動程式檔案,甚至你可以刪除當前正在執行的驅動檔案。但是,你可以告訴載入器你希望驅動的哪部分是可分頁,所謂可分頁,就是可...