1.静态映射
通过OAL中OEMAddressTable来定义。OEMAddressTable定义了从4GB的物理地址空间到内核512MB未映射的虚拟地址空间的映射关系。内核将会从这个表中创建两个虚拟地址空间段。一个是有缓冲的,一个是没有缓冲的。静态映射的虚拟地址空间只能在内核模式下访问。
作为OEMAddressTable的补充,还可以调用CreateStaticMapping来完成物理地址到虚拟地址的映射。函数返回一个未缓冲区域的虚拟地址,当然也只能由内核访问(an uncached memory region)。一个静态映射只能在启动时间(at boot time)创建而不是能够动态创建的。一个静态映射被创建后会一直有效直到设备重启。
2. 2.动态映射
主要是通过VirtualAlloc和VirtualCopy两个函数来实现。首先VirtualAlloc保留好一段虚拟地址,在保留时应该指定MEM_RESERVE和PAGE_NOACCESS标志而且保留的区域大小至少为2M,因为这样被就会分配到本进程地址空间外的地址,否则就会分配在本进程的地址空间内,会受到32M空间大小的限制。由VirualCopy来完成物理地址的映射。可以映射一段实际的RAM区域或外围设备的寄存器地址(这样就可以操作外围设备了)。
使用VirualCopy的注意事项有虚拟地址的page offset和物理地址的page offset必须相同,因为一个虚拟地址页只能够被映射到一个物理地址页,否则就会调用失败。在映射一段物理地址区域时,应该指定PAGE_PHYSICAL和PAGE_NOCACHE, 而且保证传入的物理地址左移8位。
在wince5.0中,设备驱动程序可以直接使用MmMapIoSpace完成物理地址到虚拟地址的映射。HalTranslateBusAddress是把某个类型的某个物理总线的地址转化为物理地址(全局的)。然后就可以使用MmMapIoSpace将物理地址映射为某个虚拟地址。TransBusAddrToVirtual直接会把一个与总线相关地址直接映射为可访问的虚拟地址。
由于驱动程序和应用程序都是运行在用户空间下。所以驱动程序有的权限,应用程序也会有。在驱动和应用中,通过上述的动态映射方法,来访问物理地址或控制设备寄存器都会容易做到。Wince5.0还有内核模式与用户模式的切换的接口SetKmode(6.0下已经不被支持),应用程序可以通过这个接口切换到内核模式下,可以通过静态映射的有效虚拟地址经过MMU直接改变某个RAM的存储内容,无需在映射,没有地址访问限制是内核模式下的特点。
显而易见在wince5.0访问物理地址和外围设备具有很大的*,应用程序的权限很大,很容易就会破坏整个系统。在接下来的wince6.0 内核有了很大的变化,虚拟内存模型与5.0大有不同,应用程序不能在用户模式下直接完成物理地址的映射了(virtualcopy映射物理地址将会是个不支持的请求),只能通过内核驱动程序来完成物理地址的映射,具体参考上篇博文介绍wince6.0下访问物理地址。