1 先是mdl的數據結構。
2 下面根據用法逐步的講解mdl數據結構的含義:
一般用法,先是 IoAllocateMdl :
原型為:
最常用的是VirtualAddress和Length。把自己的NonPageable buffer的起始地址傳給IoAllocateMdl ,長度也傳給他。
可是這個函數具體做了啥呢(下面只是些基本的影響理解的部分,具體更多的東西,更細節的東西,自己去看WRK的代碼)?
- 根據length和VirtualAddress算出這塊buffer總共跨越了幾個virtual page。
- 分配MDL的內存----包括上面介紹的struct _MDL(屬於head部分),ULONG型body部分。
其中PFN_NUMBER 為ULONG, IOP_FIXED_SIZE_MDL_PFNS代表pte的個數。 -
申請完了后,對mdl進行初始化
從這個圖中可以很明顯得看書上面數據結構的含義:
1 size---body + head部分的總大小。
2 StartVa----代表buffer開頭處所在page的開始地址。
3 ByteOffset----代表buffer開頭處相對於StartVa的偏移量。
然后使用MmBuildMdlForNonPagedPool將pte中的頁表項都放入mdl中的body部分。
這里show一下關鍵性代碼:
這樣mdl結構整體的構建就結束了,開始使用mdl。使用MmMapLockedPagesSpecifyCache將MDL中存儲的physical address page映射到虛擬地址中。
代碼較多,不看了。但是看看函數原型應該就能明白:
這樣的話,返回值就是我們重新映射的虛擬地址。就可以使用這個虛擬地址進行訪問了。
以上只是最簡單的基本用法,但也是最常用的。