QJE
QJE
驱动小牛
驱动小牛
  • 注册日期2001-08-09
  • 最后登录2016-01-09
  • 粉丝0
  • 关注0
  • 积分470分
  • 威望49点
  • 贡献值0点
  • 好评度44点
  • 原创分0分
  • 专家分0分
阅读:2045回复:10

DMA缓冲区的虚拟地址传到应用程序不能进行操作?

楼主#
更多 发布于:2002-07-12 15:09
首先确定DMA在中断可以做。
但是我想把DMA的虚拟地址传到应用程序里(DMA的虚拟地址是用函数VirtualAddress得到),应用程序不能对这个虚拟地址操作(比如写文件)。

最新喜欢:

kxgchinakxgchi... dongjundongju...
mengzi
驱动牛犊
驱动牛犊
  • 注册日期2001-08-02
  • 最后登录2004-05-25
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
沙发#
发布于:2002-07-12 16:07
不太清楚你这是什么意思?一般来说,没有必要在内核级分配缓冲区,DMA的缓冲区就是用户缓冲区,其地址是通过直接IO方式传递过来的,在用户态当然可以任意访问用户缓冲区而不需要知道虚拟地址,DMA需要缓冲区的虚拟地址是为了分配映射寄存器(复制用户缓冲区的物理地址连续的逻辑空间)和进行分割传输,但也并不需要显式操作虚拟地址
shaht
驱动牛犊
驱动牛犊
  • 注册日期2001-09-14
  • 最后登录2003-12-24
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
板凳#
发布于:2002-07-12 16:49
当然不能用,此地址与进程无关,到了应用程序,还不知指到哪
去了
QJE
QJE
驱动小牛
驱动小牛
  • 注册日期2001-08-09
  • 最后登录2016-01-09
  • 粉丝0
  • 关注0
  • 积分470分
  • 威望49点
  • 贡献值0点
  • 好评度44点
  • 原创分0分
  • 专家分0分
地板#
发布于:2002-07-12 16:58
我需要进行32M字节的DMA传输,必须使用连续的物理地址。所以32M的缓冲必须在内核态分配。将缓冲区物理地址转为虚拟地址传回用户,但是问题是现在用户态不能对其写操作。
QJE
QJE
驱动小牛
驱动小牛
  • 注册日期2001-08-09
  • 最后登录2016-01-09
  • 粉丝0
  • 关注0
  • 积分470分
  • 威望49点
  • 贡献值0点
  • 好评度44点
  • 原创分0分
  • 专家分0分
地下室#
发布于:2002-07-12 17:13
当然不能用,此地址与进程无关,到了应用程序,还不知指到哪
去了


那我该如何把DMA缓冲区的虚拟地址传给应用程序呢?
wuqix
驱动小牛
驱动小牛
  • 注册日期2001-03-23
  • 最后登录2008-06-09
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
5楼#
发布于:2002-07-13 22:20
这样做你首先要搞清楚3种不同的地址,物理地址,核心地址,应用层虚地址,应用层虚地址和进程有关,在核心层随便开一个缓冲区就传给应用程序当然不行,做dma的时候,用来做dma的内存实际上有两个不同的地址,一个是物理地址,用来给硬件的,另一个是内核程序用来访问这片缓冲区的核心地址,这两个地址相当于同一块内存的两个别名。如果希望应用程序访问缓冲区尽量快一些的话,通常做法是把这个核心地址映射到应用程序的进程地址空间去,这样应用程序就能直接访问缓冲区而不用有内核切换的开销了。相关函数ddk里都有,你查查就知道了。
QJE
QJE
驱动小牛
驱动小牛
  • 注册日期2001-08-09
  • 最后登录2016-01-09
  • 粉丝0
  • 关注0
  • 积分470分
  • 威望49点
  • 贡献值0点
  • 好评度44点
  • 原创分0分
  • 专家分0分
6楼#
发布于:2002-07-13 22:25
谢谢上面这位高手的回答。
那么在DS中有相关的函数吗?请告之。
mengzi
驱动牛犊
驱动牛犊
  • 注册日期2001-08-02
  • 最后登录2004-05-25
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
7楼#
发布于:2002-07-15 11:36
QJE兄台:
   驱动程序不是这么写的,虽然可以在内核分配缓冲区,但对于DMA驱动程序模型,任何一本翻译过来的驱程编写的书,都是在用户态分配一个缓冲区(当然此时是可分页的),然后将此缓冲区的虚拟地址和长度通过直接IO方式传递到内核级,通过MDL来锁定用户缓冲区(非分页),然后通过IoMapTransfer函数,将用户缓冲区的物理碎片映射到一块物理地址连续的映射寄存器(逻辑空间),这是个复制过程。。。
mengzi
驱动牛犊
驱动牛犊
  • 注册日期2001-08-02
  • 最后登录2004-05-25
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
8楼#
发布于:2002-07-15 12:13
。。。接上,这个逻辑空间是有限的,因为系统允许的映射寄存器的个数在NT/2K下通常为0x10个,也就是说最多(通常是小于)可以一次分配16×4KBs的逻辑空间(说到逻辑空间当然是物理地址连续的,如同卡上的物理地址均为逻辑地址一样),所以对于32M的缓冲区一定要进行分割传输。单纯从缓冲区看,一共分配了32M(用户级)+64K(内核级)的缓冲区。您的缓冲区的使用,正好与此相反,是在内核级分配32M缓冲区,然后极力想将这个内核级缓冲区对于用户态可见,即便你可以获取这个内核级缓冲区的CPU核心虚拟地址,但也无法访问,因为它根本不是用户态的虚拟地址,再说了,您也无权从用户态直接访问内核态,要不然怎么叫保护模式呢,您说是不?
HJY
HJY
驱动牛犊
驱动牛犊
  • 注册日期2002-04-15
  • 最后登录2002-07-24
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
9楼#
发布于:2002-07-16 01:28
有办法,如下所述:
1)在DriverEntry中用MmAllocateContiguousMemory分配物理连续的缓冲区,得到其返回的虚拟地址va;
2)用va调IoAllocateMdl接着调MmBuildMdlForNonPagedPool得到Mdl指针pMdl;
3)用pMdl调MmMapLockedPagesSpecifyCache可得到应用程序(用户层)可访问的地址(选择UserMode方式);
4)此方法仅适用于WDM1.0(非NT操作系统);
QJE
QJE
驱动小牛
驱动小牛
  • 注册日期2001-08-09
  • 最后登录2016-01-09
  • 粉丝0
  • 关注0
  • 积分470分
  • 威望49点
  • 贡献值0点
  • 好评度44点
  • 原创分0分
  • 专家分0分
10楼#
发布于:2002-07-16 15:08
看了那么多人帮我的忙,谢谢!
我自己在调调看!

游客

返回顶部