wince6.0提供了两个升级版的内存分配和映射函数,VirtualAllocEx和VirtualCopyEx,就是在原版的基础之上增加了一个进程句柄函数,所以可以在内核驱动中先获取调用者进程的句柄,再用上述的两个Ex函数,为该进程保留空间和映射物理地址。保留好的空间地址,在内核驱动中和用户进程中都是有效的。(在驱动中有效是因为用户进程是该驱动的调用者进程)。完成映射之后,就可以在用户进程中直接改变物理地址的值了。
下面介绍下这个两个函数的使用。
被映射的物理地址应该向上取整,保证为页面的起始处。所以被映射的大小也要做相应的增加。sDevPhysAddr是被映射的起始物理地址。dwSize是映射的大小。
SourcePhys = sDevPhysAddr & ~(PAGE_SIZE - 1);
SourceSize = dwSize + (sDevPhysAddr & (PAGE_SIZE - 1));
lpUserAddr=VirtualAllocEx(hDesProcess, 0, SourceSize, MEM_RESERVE,PAGE_NOACCESS);其它的参数,除了进程句柄外与vitrualalloc virtualcopy都是相同的。对于VirtualCopyEx来说
用户进程的句柄是目标进程句柄,驱动所在的进程句柄是源进程句柄。
由于物理地址向上取整,所以映射完成后的虚拟地址应该做出调整:
lpUserAddr=(LPVOID)((ULONG)lpUserAddr+(sDevPhysAddr & (PAGE_SIZE - 1)));
gUserAddr = lpUserAddr;
返回真正所需的地址。
当使用完后,释放资源如下:
VirtualFreeEx(pvProcess,(PVOID)((ULONG)gUserAddr&~(ULONG)(PAGE_SIZE-1)),0,MEM_RELEASE);
完成上述内容,首先是做个简单的流模式的内核驱动(见资源中心的FirstSubDll.rar),笔者在应用程序,用户模式驱动,内核驱动三个环境下VirtualAllocEx和VitualCopyEx映射物理地址做过测试。只有内核驱动能完成,其他的都是不支持的请求。Wince6.0限制的应用程序对物理地址的访问,提高系统的安全性,只有内核驱动(被系统信赖的)才能访问物理地址及外围设备寄存器。在驱动中给出IOCTL接口,通过DeviceIoControl完成物理地址映射和资源释放。应用加载驱动调用接口,获取完成映射的虚拟地址,直接读写,可以改变RAM值或某个外围设备寄存器的值(如通过GPIO控制某个设备的电源开关)。
前面提到过的保留好的空间地址,在内核驱动中和用户进程中都是有效的。通过此点可以让内核驱动和应用程序共享一段物理RAM。内核进程和用户进程内存共享与拷贝内核驱动中的数据块到用户已分配的存储空间中相比,可以节省内存资源和提高效率。特别是在摄影设备中,需要大量的存储,若不再应用和驱动中共享内存,就会损失大量的RAM资源。
来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/23410886/viewspace-1031512/,如需转载,请注明出处,否则将追究法律责任。
转载于:http://blog.itpub.net/23410886/viewspace-1031512/