在Windows 10驱动程序中将内核空间虚拟地址映射到用户空间虚拟地址

3
我正在Windows 10(64位)中编写内核模式驱动程序,其主要目的是从DMA读取数据。我想知道是否可以将地址暴露给用户空间(当然不是物理地址),而不是将内核空间中的内存块复制到用户空间分配的缓冲区中,并避免进行内存复制操作。
也许可以这样做:
1. 分配一块连续的物理内存(并将物理地址映射到内核空间中的虚拟地址)。 2. 将内核空间中的虚拟地址映射到用户空间中的虚拟地址。
顺便提一下,由于只有一个内核空间,而系统中运行的进程数与用户空间数量相同(是吗?),因此我必须使用某种调用进程的句柄,以便在适当的进程中获取虚拟地址...
感谢您的时间!

为什么不让内核从一开始就与用户空间缓冲区一起工作呢? - Eugene Sh.
据我所了解,如果我在用户空间分配缓冲区,不能保证它在物理内存中是连续的(只在当前进程的虚拟内存中连续),我需要向位于PCIe插槽上的设备揭示一个地址,从而可以开始连续写入。 - Jones
也许这个链接会有用:https://dev59.com/GWw05IYBdhLWcg3wszwl,虽然表面上看起来只是处理文件。 - yano
让用户进程将用户空间的_virtual_地址[和长度]传递给您的内核驱动程序。您的_driver_可以/应该决定是否可以绕过中间缓冲区[或不绕过]。驱动程序可以挂起进程,锁定页面,确定I/O空间物理地址,并生成分散/聚集DMA操作[可能使用I/O MMU]。关键点是驱动程序更适合处理所有这些事情。您可以让用户进程请求驱动程序执行缓冲区分配[从连续内存]并将其传递回进程。 - Craig Estey
如果您成功地将其公开(而不是复制),那么在单个内核空间上,您不会遇到多进程冲突吗? - Serge
1个回答

1
对于您的问题(2),可以考虑使用MmMapLockedPagesSpecifyCache()并设置AccessMode = UserMode。请注意重要的警告:“该例程返回一个用户地址,该地址在驱动程序正在运行的进程上下文中有效”,因此您需要确保驱动程序在您的用户模式应用程序的进程中运行时执行映射,例如通过在直接处理来自用户模式代码的调用的驱动程序代码中进行映射,例如DeviceIoControl()。另请注意,要使用此函数,您需要提供描述物理页面的MDL,并且这些页面必须被锁定。

注意页面锁定,否则你的驱动程序会出现内存泄漏错误。每次因为某个驱动程序锁定了一半的内存而不得不重启Windows都很恼人。 - Zan Lynx

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接