MapPtrToProcess 用法 WINCE驱动分析3
下,看看应用程序的代码:
COPY_STRUCT cs[1];
auto char data1[10];
auto char data2[10];
cs结构和data1,data2数组都是自动变量,存放在堆栈里。假设这个应用程序被加载到0x18000000位置的slot里,那么他们的地址都是0x18XXXXXX。不熟悉wince memory architecture的可以看看资料,了解一下slot。当调用了
DeviceIoControl,按照文档的说法,cs指针得到了转换,因为从应用程序的进程转到了device.exe进程,而device进程又是当前的运行的进程,被映射到了slot0,系统负责转换cs指针。而cs包含的pBuffer1和pBuffer2是没有映射不能直接用的。
事实上,我们传过来的指针根本就是不需要映射,因为他们都是0x18xxxxxx,在应用程序的slot里,所以只要device.exe有访问应用程序的权限,就可以了。而这个权限,系统已经帮我们设置好了。
那什么情况下要自己映射呢?
如果应用程序在定义 data1和data2使用static关键字,或者使用LocalAlloc,HeapAlloc的时候,一定要自己映射cs里的指针。
在应用程序里这样写:
cs.pBuffer1 = (char *)malloc(10);
cs.pBuffer2 = (char*)malloc(10);
cs.nLen = 10;
如果不使用MapPtrToProcess完成映射,那就出现data abort exception.
为什么呢?
因为这些变量都是在堆里分配的,而当应用程序运行时,被映射到slot0,堆的地址也就是处于slot的范围内,传递到device.exe后,device.exe被映射到了slot0,这个时候必须要将应用程序的指针映射回应用程序所在的slot。否则访问的是device.exe的空间,会发生不可知道的结果。
验证一下上面说的地址分配问题。
我们这样定义
COPY_STRUCT cs[1];
static char data1[10]; 堆里
auto char data2[10]; 栈里
这样赋值:
cs[0].pBuffer1 = data1[0];
cs[0].pBuffer2 = data2[0];
cs[0].nLen = 10;
调试信息:
cs[0].pBuffer1 = data1[0];
180112D0 ldr r2, [pc, #0xD0]
180112D4 str r2, [sp, #0x10]
读取data1[0]使用的是PC作为基址,而此时的应用程序处于运行阶段映射到slot0,那么pc也就在0~01ffffff范围,我的调试结果是在0x000112D0+8,使用的是arm,流水线机制,当前指令地址+8才是pc值。
143: cs[0].pBuffer2 = data2[0];
180112D8 add r0, sp, #0x20
180112DC str r0, [sp, #0x14]
读取data2[0]采用的是sp作为基址,sp在应用程序加载到slot的时候就确定了的。所以保持了在应用程序slot的值,处于0x18xxxxxx范围。
我们看到因为wince的slot机制,我们有时候需要映射,有时候不需要。所以wince文档说结构里的指针要映射。毕竟你不知道应用程序怎么写。
当然,你可以根本不映射,只要把那个结构屏蔽调,写一个STATIC LIBRARY给用户使用,自己保证使用正确的地址分配就可以了。上面我说的那个家伙就是这么干的。
好了,接着调用:
CloseHandle(hnd);
程序结束了,完成了一次简单的拷贝。
这个框架完成了,driver的基本接口设计,强调了内存指针的使用问题。但是相对于一个真正的driver,还缺少点东西,就是访问硬件的方法。下面继续讨论如何访问硬件
嵌入式新闻 嵌入式资料 嵌入式培训 嵌入式linux 嵌入式系统 嵌入式开发 嵌入式 相关文章:
- 煤矿井下综合自动化系统中的应用(04-06)
- 软件Overlay:程序编写与调试(01-20)
- USB数据通信接□模块的程序设计(10-17)
- 东江产业园:力争2017年产值达千亿(09-30)
- 硅谷数模的SlimPort扩大了Nexus7的显示屏选择(08-01)
- Lonworks控制网络技术在城市排水泵站自动化中的应用(06-06)