milkyway1888
驱动牛犊
驱动牛犊
  • 注册日期2006-10-08
  • 最后登录2011-05-07
  • 粉丝1
  • 关注0
  • 积分6分
  • 威望97点
  • 贡献值0点
  • 好评度91点
  • 原创分0分
  • 专家分0分
阅读:2644回复:13

请教大家关于虚实地址映射的几个问题

楼主#
更多 发布于:2007-03-08 19:09
  1.我看到网上有这样的理解:

----- OEMAddressTable (MMU) -----       ------------- WinCE OS -------------------
/                                   \               /                                       \
硬件地址   --------------------->   物理地址(或逻辑地址) -------------------------> 虚拟地址


"硬件地址到物理地址(或逻辑地址)的映射是由MMU控制的, 物理地址(或逻辑地址)到虚拟地址的映射是有WINCE OS控制的."
      而我的理解是wince内核如HAL访问I/O,只需要在 OEMAddressTable 中做静态的虚实地址映射就可以了;而在应用程序中是通过使用 VirtualAlloc 和 VirtualCopy (或者直接调用 MmmapIoSpace 函数)来实现动态地址映射的.即不是递进关系,而是并列关系.只是实现的映射方式和阶段不同,不知道XD们有何见解?

2,在帮助中有这样一段
#include <windows.h>

#define PHYSADDR  ((PVOID)0x10000000)
// PHYSADDR is the physical address of the peripheral
// registers

#define SIZE  (4800*4)

LPVOID lpv;
BOOL bRet;

lpv = VirtualAlloc(0, SIZE, MEM_RESERVE, PAGE_NOACCESS);


printf(TEXT("VirtualAlloc reservation @%8.8lx\r\n"), lpv);
bRet = VirtualCopy(lpv, PHYSADDR>>8, SIZE, PAGE_READWRITE | PAGE_NOCACHE | PAGE_PHYSICAL);

上述的第二个参数:PHYSADDR>>8,为什么要右移两个BYTES呢?
问的浅陋,请大家指教.
microsun
论坛版主
论坛版主
  • 注册日期2002-11-11
  • 最后登录2014-07-18
  • 粉丝0
  • 关注0
  • 积分1052分
  • 威望1159点
  • 贡献值0点
  • 好评度848点
  • 原创分0分
  • 专家分0分
沙发#
发布于:2007-03-10 20:57
第一个问题我觉得你的理解是对的,
第二个问题,你仔细看一下帮助就知道了.
右移8位就是把这个值除以256
学海无涯
milkyway1888
驱动牛犊
驱动牛犊
  • 注册日期2006-10-08
  • 最后登录2011-05-07
  • 粉丝1
  • 关注0
  • 积分6分
  • 威望97点
  • 贡献值0点
  • 好评度91点
  • 原创分0分
  • 专家分0分
板凳#
发布于:2007-03-12 09:25
谢谢microsun!
我还有两个个疑问(1)在使用virtualcopy时物理地址右移8位是不是必须的?或者说什么时候需要这样做?
(2)下面这个函数的第四个参数同时选择readwrite/nocache/physical的意图是可读写无缓存的物理地址对吗?一般映射物理地址这个参数应该如何选择?
bRet = VirtualCopy(lpv, PHYSADDR>>8, SIZE, PAGE_READWRITE | PAGE_NOCACHE | PAGE_PHYSICAL);
zhengshijie
驱动小牛
驱动小牛
  • 注册日期2003-07-11
  • 最后登录2009-03-18
  • 粉丝1
  • 关注0
  • 积分8分
  • 威望217点
  • 贡献值0点
  • 好评度199点
  • 原创分3分
  • 专家分0分
地板#
发布于:2007-03-12 13:16
为了找到这个问题的答案,我查看了源代码,从代码中可以得到这个信息,VirtualCopy()对应private\winceos\coreos\nk\kernel\virtmem.c->DoVirtualCopy()从这个代码中可以看到,当VirtualCopy(,LPVOID lpvSrc,..) lpvSrc是物理地址时需要右移8,同时PAGE_PHYSICAL需要设置。负责源地址就是虚地址时不需要右移8,并且PAGE_PHYSICAL也不要设置。仔细看了DoVirtualCopy()相信会对这个有更深刻的理解。
milkyway1888
驱动牛犊
驱动牛犊
  • 注册日期2006-10-08
  • 最后登录2011-05-07
  • 粉丝1
  • 关注0
  • 积分6分
  • 威望97点
  • 贡献值0点
  • 好评度91点
  • 原创分0分
  • 专家分0分
地下室#
发布于:2007-03-12 16:04
看了下DoVirtualCopy()的代码,说说我的理解看看对不?
大约是说在fdwProtect & PAGE_PHYSICAL=1时,里头会执行dwSrcAddr<<8。也就是说如果virtualcopy()的第四个参数为page_physical时,也自动的把物理地址左移两个字节,所以在执行virtualcopy且目标页的存取类型为page_physical时,需要先把物理地址右移两个字节,这样才是对正确物理地址进行操作。
那么如果目标页的存取类型不是page_physical时,比如page_noaccess时,是不是就直接给物理地址就可以了呢?zhengshijie 提到的源地址是虚地址又是什么情况呢?virtualcopy的作用不就是做虚拟到物理地址的映射吗?如果源地址是虚地址,那映射还有什么意义?
理解肤浅请指正,谢谢
milkyway1888
驱动牛犊
驱动牛犊
  • 注册日期2006-10-08
  • 最后登录2011-05-07
  • 粉丝1
  • 关注0
  • 积分6分
  • 威望97点
  • 贡献值0点
  • 好评度91点
  • 原创分0分
  • 专家分0分
5楼#
发布于:2007-03-12 16:27
又看了下HELP里头关于virtualcopy()的,里头提到第四个参数设置成page_physical时,要把源地址除以256。不过看了源代码才知道为什么:)
什么虚拟地址物理地址看的我云里雾里的
zhengshijie
驱动小牛
驱动小牛
  • 注册日期2003-07-11
  • 最后登录2009-03-18
  • 粉丝1
  • 关注0
  • 积分8分
  • 威望217点
  • 贡献值0点
  • 好评度199点
  • 原创分3分
  • 专家分0分
6楼#
发布于:2007-03-13 15:55
这个源地址是虚地址(是在内核的虚地址),映射到用户进程中的虚拟地址空间,像这种用法你看CE4.2的S3C2440 BSP代码可以找到,
#define IOP_BASE      0xB1600000 // 0x56000000
v_pIOPRegs = VirtualAlloc(0, sizeof(IOPreg), MEM_RESERVE, PAGE_NOACCESS);
VirtualCopy((PVOID)v_pIOPRegs, (PVOID)IOP_BASE, sizeof(IOPreg), PAGE_READWRITE|PAGE_NOCACHE)
milkyway1888
驱动牛犊
驱动牛犊
  • 注册日期2006-10-08
  • 最后登录2011-05-07
  • 粉丝1
  • 关注0
  • 积分6分
  • 威望97点
  • 贡献值0点
  • 好评度91点
  • 原创分0分
  • 专家分0分
7楼#
发布于:2007-03-14 08:53
0xB1600000(虚) 对应 0x56000000(实) 是在OEMAddressTable中规定的?
VirtualCopy函数不是用于映射物理地址到虚拟地址的吗?怎么也可以映射虚拟到虚拟?还是说这里的源地址是内核认为的物理地址=处理器的虚拟地址?
回到我原来的第一个问题上了,究竟是如何映射地址的?
能否这样理解: 在OAL访问I/O,只需要在OEMAddressTable中做CPU到虚拟的映射? 而在驱动或应用程序中访问I/O,既可以通过OEMAddressTable+VirtualCopy方式,也可以直接用MmMapIoSpace?
rilyyu
驱动小牛
驱动小牛
  • 注册日期2006-11-17
  • 最后登录2010-08-17
  • 粉丝0
  • 关注0
  • 积分512分
  • 威望130点
  • 贡献值0点
  • 好评度127点
  • 原创分0分
  • 专家分0分
8楼#
发布于:2007-03-14 09:37
VirtualCopy可以把非自己进程空间的虚拟地址映射到自己的进程空间,原理就是把2个虚拟地址映射到一个物理地址。每个应用程序都有自己独立的进程空间,即使它知道一个虚拟地址但不在自己的进程空间内也不可以直接访问的,所以需要虚拟到虚拟的映射。
rilyyu
驱动小牛
驱动小牛
  • 注册日期2006-11-17
  • 最后登录2010-08-17
  • 粉丝0
  • 关注0
  • 积分512分
  • 威望130点
  • 贡献值0点
  • 好评度127点
  • 原创分0分
  • 专家分0分
9楼#
发布于:2007-03-14 09:44
由OEMAdderessTable决定的虚拟地址对于内核来说就是物理地址了,内核会在这个基础上再虚拟出一个地址来给每个进程使用, 我是这么理解的,和大家讨论一下。真理越辨越明。召唤达人释疑
milkyway1888
驱动牛犊
驱动牛犊
  • 注册日期2006-10-08
  • 最后登录2011-05-07
  • 粉丝1
  • 关注0
  • 积分6分
  • 威望97点
  • 贡献值0点
  • 好评度91点
  • 原创分0分
  • 专家分0分
10楼#
发布于:2007-03-15 09:42
引用第6楼zhengshijie2007-03-13 15:55发表的“”:
这个源地址是虚地址(是在内核的虚地址),映射到用户进程中的虚拟地址空间,像这种用法你看CE4.2的S3C2440 BSP代码可以找到,
#define IOP_BASE      0xB1600000 // 0x56000000
v_pIOPRegs = VirtualAlloc(0, sizeof(IOPreg), MEM_RESERVE, PAGE_NOACCESS);
VirtualCopy((PVOID)v_pIOPRegs, (PVOID)IOP_BASE, sizeof(IOPreg), PAGE_READWRITE|PAGE_NOCACHE)



0xB1600000(虚) 对应 0x56000000(实) 是在OEMAddressTable中规定的?
上面代码里VirtualCopy实现了把0xB1600000(内核段虚拟地址)映射到当前进程的虚拟地址(低2G段)?
也就是说经过OEMAddressTable,实现的只是CPU物理地址到OS内核虚拟地址的一次映射,如果需要在应用程序中访问,还要再用VirtuaAlloc+VirtualCopy做一个内核到当前进程的二次映射?
milkyway1888
驱动牛犊
驱动牛犊
  • 注册日期2006-10-08
  • 最后登录2011-05-07
  • 粉丝1
  • 关注0
  • 积分6分
  • 威望97点
  • 贡献值0点
  • 好评度91点
  • 原创分0分
  • 专家分0分
11楼#
发布于:2007-03-15 09:49
引用第8楼rilyyu2007-03-14 09:37发表的“”VirtualCopy可以把非自己进程空间的虚拟地址映射到自己的进程空间,原理就是把2个虚拟地址映射到一个物理地址。每个应用程序都有自己独立的进程空间,即使它知道一个虚拟地址但不在自己的进程空间内也不可以直接访问的,所以需要虚拟到虚拟的映射。


我看了帮助里VirtualCopy的功能说明: binds a specific physical memory range to a statically mapped virtual address. 不是用于映射物理地址到虚拟地址的吗?个人英文是否理解错误?

还是说应该这样理解: OEMAddressTable中做CPU到虚拟的映射,这里的虚拟是对于CPU而言的;到了OS里,这里的virtual address就成了physical address?

十分期待明确的释疑!!
rilyyu
驱动小牛
驱动小牛
  • 注册日期2006-11-17
  • 最后登录2010-08-17
  • 粉丝0
  • 关注0
  • 积分512分
  • 威望130点
  • 贡献值0点
  • 好评度127点
  • 原创分0分
  • 专家分0分
12楼#
发布于:2007-03-15 14:00
关于VirtualCopy我说错了,后面的说法也不对,我把CE当成每个程序拥有4G的内存空间了.大家就当我为了活跃论坛气氛,信口开河把 .待我回去研究研究先.关注这个帖子.
milkyway1888
驱动牛犊
驱动牛犊
  • 注册日期2006-10-08
  • 最后登录2011-05-07
  • 粉丝1
  • 关注0
  • 积分6分
  • 威望97点
  • 贡献值0点
  • 好评度91点
  • 原创分0分
  • 专家分0分
13楼#
发布于:2007-03-15 16:39
wxl_50685330斑竹的老帖里提到关于virtualcopy()的第二个参数似乎既可以是经过OEMAddressTable得到的内核段虚拟地址,也可以是物理地址.只是后者需要右移8位来对齐.不知道我的理解正确否...
游客

返回顶部