1. 程式人生 > >瞭解MmMapIoSpace以及MmUnmapIoSpace函式的實現原理以及實現方法

瞭解MmMapIoSpace以及MmUnmapIoSpace函式的實現原理以及實現方法

分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow

也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!

               

瞭解MmMapIoSpace以及MmUnmapIoSpace函式的實現原理以及實現方法

Code
  1 原始碼路徑
  2 H:/WINCE600/PUBLIC/COMMON/OAK/DRIVERS/CEDDK/DDK_MAP
  3 目的,瞭解MmMapIoSpace以及MmUnmapIoSpace函式的實現原理以及實現方法
  4 分析之前,要看看一個很關鍵的東西——PHYSICAL_ADDRESS,這個引數很重要,是地址的組織形式。
  5 // in ceddk.h
  6 typedef LARGE_INTEGER PHYSICAL_ADDRESS, 
*PPHYSICAL_ADDRESS;
  7 // in winnt.h
  8 typedef struct _LARGE_INTEGER {
  9 #else // MIDL_PASS
 10 typedef union _LARGE_INTEGER {
 11     struct {
 12         DWORD LowPart;
 13         LONG HighPart;
 14     };
 15     struct {
 16         DWORD LowPart;
 17         LONG HighPart;
 18     } u;
 19 #endif //MIDL_PASS
 20     LONGLONG QuadPart;
 21 } LARGE_INTEGER;
 22 在MSDN中有這樣的解釋:
 23 LARGE_INTEGER Union
 24 
 25 The LARGE_INTEGER structure is used to represent a 64-bit signed integer value.
 26 
 27 Note  Your C compiler may support 64-bit integers natively. For example, Microsoft Visual C++ supports the __int64 sized integer type. For 
 28 
 29 more information, see the documentation included with your C compiler.
 30 
 31 Members
 32 LowPart 
 33 Low-order 32 bits.
 34 
 35 HighPart 
 36 High-order 32 bits.
 37 
 38 
 39 LowPart 
 40 Low-order 32 bits.
 41 
 42 HighPart 
 43 High-order 32 bits.
 44 
 45 QuadPart 
 46 Signed 64-bit integer.
 47 
 48 Remarks
 49 The LARGE_INTEGER structure is actually a union. If your compiler has built-in support for 64-bit integers, use the QuadPart member to store 
 50 
 51 the 64-bit integer. Otherwise, use the LowPart and HighPart members to store the 64-bit integer.
 52 
 53 
 54 OK,現在就來看看MmMapIoSpace吧。
 55 首先看它的一個成功使用例子:
 56 
 57 void CDlgDemoDlg::OnButton1()   
 58 {   
 59 // TODO: Add your control notification handler code here   
 60 //unsigned char *gpio_base;   
 61 unsigned int *gpio_base;   
 62 OutputDebugString(L"TestDrv - LedDrive1/n");   
 63 //PUCHAR ioPortBase;   
 64 PHYSICAL_ADDRESS PortAddress = {0x560000600}; //  LowPart=0x56000060;HighPart=0;
 65 gpio_base =(unsigned int *)MmMapIoSpace( PortAddress, 0x04,FALSE ); // 獲得記憶體,4位元組大小。   
 66 *gpio_base = 0x0585ff87// 直接訪問硬體   
 67 MmUnmapIoSpace(gpio_base,0x04);//釋放記憶體   
 68 }  
 69 本文來自CSDN部落格,轉載請標明出處:http://blog.csdn.net/gooogleman/archive/2009/05/16/4189536.aspx
 70 
 71 再看MmMapIoSpace實現過程H:/WINCE600/PUBLIC/COMMON/OAK/DRIVERS/CEDDK/DDK_MAP
 72 
 73 /*++
 74 Routine Description:
 75   map the given physical address range to nonpaged system space
 76 
 77 Arguments:
 78   PhysicalAddress - starting physical address of the I/O range to be mapped
 79   NumberOfBytes - number of bytes to be mapped
 80   CacheEnable - TRUE if the physical address range can be mapped as cached
 81                 memory
 82 
 83 Return Value:
 84   base virtual address that maps the base physical address for the range, or
 85   NULL if space for mapping the range is insufficient
 86 --*/
 87 PVOID
 88 MmMapIoSpace (
 89     IN PHYSICAL_ADDRESS PhysicalAddress,
 90     IN ULONG NumberOfBytes,
 91     IN BOOLEAN CacheEnable
 92     )
 93 {
 94     PVOID   pVirtualAddress;
 95     ULONGLONG   SourcePhys;
 96     ULONG   SourceSize;
 97     BOOL    bSuccess;
 98 
 99     //
100     // Page align source and adjust size to compensate
101     //
102 
103     SourcePhys = PhysicalAddress.QuadPart & ~(PAGE_SIZE - 1);// for page align
104     SourceSize = NumberOfBytes + (PhysicalAddress.LowPart & (PAGE_SIZE - 1));
105 
106     if (SourceSize < NumberOfBytes) { // Prevent Integer overflow.
107         SetLastError(ERROR_INVALID_PARAMETER);
108         return NULL;
109     }
110     
111 
112     pVirtualAddress = VirtualAlloc(0, SourceSize, MEM_RESERVE, PAGE_NOACCESS);
113 
114     if (pVirtualAddress != NULL)
115     {
116         bSuccess = VirtualCopy(
117             pVirtualAddress, (PVOID)(SourcePhys >> 8), SourceSize,
118             PAGE_PHYSICAL | PAGE_READWRITE | (CacheEnable ? 0 : PAGE_NOCACHE));
119 
120         if (bSuccess)
121         {
122             (ULONG)pVirtualAddress += PhysicalAddress.LowPart & (PAGE_SIZE - 1);//保證虛擬地址是頁對齊
123         }
124         else
125         {
126             VirtualFree(pVirtualAddress, 0, MEM_RELEASE);//釋放記憶體。
127             pVirtualAddress = NULL;
128         }
129     }
130 
131     return pVirtualAddress;//返回虛擬記憶體地址。
132 }
133 
134 =================================================================================
135   從這個看來MmMapIoSpace也是使用了驅動中常用的VirtualAlloc、VirtualCopy、VirtualFree來實現的,只不過是加入了頁對齊,使用起來較安全。
136   再看看MmUnmapIoSpace
137 
138 /*++
139 Routine Description:
140   unmap a specified range of physical addresses previously mapped by
141   MmMapIoSpace
142 
143 Arguments:
144   BaseAddress - pointer to the base virtual address to which the physical
145                 pages were mapped
146   NumberOfBytes - number of bytes that were mapped
147 
148 Return Value:
149   None
150 --*/
151 VOID
152 MmUnmapIoSpace (
153     IN PVOID BaseAddress,
154     IN ULONG NumberOfBytes
155     )
156 {
157     VirtualFree((PVOID)((ULONG)BaseAddress & ~(ULONG)(PAGE_SIZE - 1)), 0, MEM_RELEASE);
158 }
159 //嘿嘿,還是使用驅動的常用方法VirtualFree來釋放虛擬記憶體,只是安全係數高一些。
160 類似參考文章:http://hi.chinaunix.net/?uid-21747227-action-viewspace-itemid-39331
161 
轉載請標明:作者[email protected]桂林電子科技大學一系科協,原文地址:http://www.cnblogs.com/wogoyixikexie/(或者我在CSDN的部落格:http://blog.csdn.net/gooogleman——如有錯誤,希望能夠留言指出;如果你有更加好的方法,也請在部落格後面留言,我會感激你的批評和分享。            

給我老師的人工智慧教程打call!http://blog.csdn.net/jiangjunshow

這裡寫圖片描述