同樣是看別人程式碼時發現的,作者使用了MmGetPhysicalAddress和MmMapIoSpace這兩個函式,之前從來沒看過這兩個函式還以為是作者自己寫的呢。後來查了一下WDK原來是有文件的函式。作者是用這個函式把快取模型I/O的地址取實體地址之後再對映出虛擬地址,雖然我沒發現這麼做有什麼意義,因為對於緩衝I/O模式來說,IRP中給出的緩衝區地址已經是I/O管理器進行復制之後的結果了,不需要再進行什麼對映,我也沒搞懂作者是要幹嗎,不過可以學習一下這兩個函式的使用。
PHYSICAL_ADDRESS
MmGetPhysicalAddress(
IN PVOID BaseAddress
);
1 PHYSICAL_ADDRESS
2 MmGetPhysicalAddress (
3 __in PVOID BaseAddress
4 )
5
6 {
7 PMMPTE PointerPte;
8 PHYSICAL_ADDRESS PhysicalAddress;
9
10 if (MI_IS_PHYSICAL_ADDRESS(BaseAddress))
11 {
12 PhysicalAddress.QuadPart = MI_CONVERT_PHYSICAL_TO_PFN (BaseAddress);
13 }
14 else
15 {
16
17 PointerPte = MiGetPdeAddress (BaseAddress);
18 if (PointerPte->u.Hard.Valid == 0)
19 {
20 KdPrint(("MM:MmGetPhysicalAddressFailed base address was %p",
21 BaseAddress));
22 ZERO_LARGE (PhysicalAddress);
23 return PhysicalAddress;
24 }
25
26 if (MI_PDE_MAPS_LARGE_PAGE (PointerPte))
27 {
28 PhysicalAddress.QuadPart = MI_GET_PAGE_FRAME_FROM_PTE (PointerPte) +
29 MiGetPteOffset (BaseAddress);
30 }
31 else
32 {
33 PointerPte = MiGetPteAddress (BaseAddress);
34
35 if (PointerPte->u.Hard.Valid == 0)
36 {
37 KdPrint(("MM:MmGetPhysicalAddressFailed base address was %p",
38 BaseAddress));
39 ZERO_LARGE (PhysicalAddress);
40 return PhysicalAddress;
41 }
42 PhysicalAddress.QuadPart = MI_GET_PAGE_FRAME_FROM_PTE (PointerPte);
43 }
44 }
45
46 PhysicalAddress.QuadPart = PhysicalAddress.QuadPart << PAGE_SHIFT;
47 PhysicalAddress.LowPart += BYTE_OFFSET(BaseAddress);
48
49 return PhysicalAddress;
50 }
PVOID
MmMapIoSpace(
IN PHYSICAL_ADDRESS PhysicalAddress,
IN SIZE_T NumberOfBytes,
IN MEMORY_CACHING_TYPE CacheType
);
順帶再說下,對於Windows記憶體管理不瞭解的童鞋可以不明白為啥獲得實體地址後不直接使用,因為對於我們來說是不能直接使用實體地址的,我們平時接觸到的都是經過分段+分頁機制轉化後的虛擬地址,而唯一能接觸到實體地址的地方我想就是CR3暫存器中儲存的PDE的基址了。