WinCE6.0中应用程序如何直接访问物理空间

     
在事实上支付进程中,平常希望能在应用程序中直接读写设备的物理空间。从前在做WinCE6.0下的MEMMgr时经过机要加载一个内核态驱动实现了这多少个需要。但这种艺术有一个显然的弱项,每回读写都必须经过它才能一呵而就。假设只是读取GPIO,这问题不算大。如若想经过这种办法实现录像播放的增速就相比较不方便了。揣摸非但不可能加快,反而会变得更慢。

     
开始曾与ZL仔细的研商过那多少个问题,他及时在WinCE6.0上移植TCPMP,发现广播录像不太流利,于是想经过直接写显存举行加速。指标很引人注目,在拔取中申请一段虚拟空间,通过某种模式将其映射到显存上,录像解码过程中一向往映射过的杜撰空间上写。这种措施与利用GAPI有某些好像。

     
实现那多少个需求,需要用到函数VirtualCopyEx()。看看匡助中关于它的注明,This
function dynamically maps a virtual address to a physical address by
creating a new page-table entry.This function is callable in kernel mode
and in user mode, when the source and destination process handles are
the active process.This function is similar to VirtualCopy, except
VirtualCopyEx requires handles to the source and destination
process.

     
据此基本可以规定,大家的确可以在应用中申请一段虚拟空间,然后通过这一个函数将其映射到某段物理空间上。其中目的经过是我们的施用,而源进程是NK.exe。为了兑现在NK.exe中履行VirtualCopyEx(),可以加载一个内核态的驱动。更为有利于的法门是移植一个OALIOCTL,并在IOControl()中添加一个case。这样,应用程序在做内存映射时就无需打开某个流驱动,直接调用KernelIoControl()即可。

      OALIOCTL中丰硕的重中之重代码如下。 

 1 typedef struct {
 2     void*    pvDestMem;
 3     DWORD    dwPhysAddr;
 4     DWORD    dwSize;
 5 } VIRTUAL_COPY_EX_DATA;
 6 
 7 #define IOCTL_VIRTUAL_COPY_EX CTL_CODE (FILE_DEVICE_UNKNOWN,3333,METHOD_BUFFERED,FILE_ANY_ACCESS)
 8 
 9 
10 case IOCTL_VIRTUAL_COPY_EX:
11 {
12     VIRTUAL_COPY_EX_DATA *p = (VIRTUAL_COPY_EX_DATA*)pInBuf;
13     HANDLE hDst = (HANDLE)GetDirectCallerProcessId();
14     HANDLE hSrc = (HANDLE)GetCurrentProcessId();
15     fRet = VirtualCopyEx(hDst,p->pvDestMem,hSrc,(LPVOID)p->dwPhysAddr,p->dwSize,
16     
PAGE_READWRITE|PAGE_PHYSICAL|PAGE_NOCACHE);
17 }break;

       应用程序中展开内存映射的要紧代码如下。

 1 volatile LPVOID GetVirtual(DWORD dwPhyBaseAddress, DWORD dwSize)
 2 {
 3     volatile LPVOID pVirtual;
 4     VIRTUAL_COPY_EX_DATA vced;
 5     
 6     if(dwPhyBaseAddress&0xFFF)
 7     {
 8         return NULL;
 9     }
10     vced.dwPhysAddr = dwPhyBaseAddress>>8;
11     pVirtual = VirtualAlloc(0,dwSize,MEM_RESERVE,PAGE_NOACCESS);
12     vced.pvDestMem = pVirtual;
13     vced.dwSize = dwSize;
14     KernelIoControl(IOCTL_VIRTUAL_COPY_EX,&vced, sizeof(vced), NULL, NULL, NULL);
15     return pVirtual;
16 }
17 
18 // WinCE6.0模拟器中应用程序直接写屏
19 PBYTE pLCDBuf = (PBYTE)GetVirtual(0x33f00000,0x100000);
20 memset(pLCDBuf,0,0×100000);
21 

       这种办法在WinCE6.0的模拟器中测试了瞬间,能达成预期的效用。

相关文章