代码之家  ›  专栏  ›  技术社区  ›  cstricklan

将物理内存映射到用户空间作为普通的、结构页支持的映射

  •  3
  • cstricklan  · 技术社区  · 7 年前

    我有一个自定义设备驱动程序,它实现了 mmap 将共享RAM缓冲区(操作系统外部)映射到用户空间的操作缓冲区是通过传递 mem=32M 作为操作系统的引导参数,剩下的512MB作为缓冲区我想从映射内存执行零拷贝操作,如果 vm_flags 包括 VM_PFNMAP VM_IO .

    我的驱动程序当前通过调用 vm_iomap_memory(vma, start, size) ,依次调用 io_remap_pfn_range remap_pfn_range ,它用 虚拟机 虚拟机 准备好了这可以将内存映射到用户空间,但是在 get_user_pages 由于 虚拟机 正在设置标志或缺少结构页的评论 重新映射范围 显示这是预期行为,因为pfn映射的内存不应被视为“正常”然而,对于我的情况,它只是一个保留的RAM块,所以我不明白为什么不应该将它视为正常的我已经设置了缓存失效/刷新来手动管理内存。

    我试过让 虚拟机 虚拟机 上的旗帜 vm_area_struct 在映射期间和映射之后,但是 获取用户页面 仍然失败我也看过dma库,但看起来它们依赖于 重新映射范围 在幕后。

    我的问题是如何将物理内存映射为普通的、非pfn的、结构页支持的用户空间地址或者有其他的方法我应该看它吗谢谢!

    1 回复  |  直到 7 年前
        1
  •  3
  •   cstricklan    6 年前

    我已经找到了一种解决方案,可以将一个内存缓冲区映射到内核外部,这需要对前面提到的几个错误的起点进行更正不可能在这里发布完整的源代码,但要使其工作的步骤是:

    1. 设备树:为没有关联驱动程序的缓冲区定义保留内存区域不要使用mem或memmap引导程序内核将限制自己在这个保留空间之外使用内存,但是现在可以为保留内存创建结构页。
    2. 在设备驱动程序(在我的例子中是LKM)中,将物理地址映射到内核虚拟地址需要使用 memremap 而不是 ioremap ,因为这是我们正在映射的真实内存。
    3. 在设备驱动程序mmap例程中,不要使用 remap_pfn_range 要为可用空间设置vma,请指定自定义 fault 没有对 vma->vm_ops.fault 在使用用户空间虚拟地址时查找页面这种方法在 lddv3 ch15 .
    4. 驱动程序中的nopage函数应该使用传递给它的vm_fault structure参数来计算需要页面的地址到vm a的偏移量然后使用该偏移量计算一个内核虚拟地址(相对于memremap的地址),并通过调用 page = virt_to_page(pageptr); ,然后调用 get_page(page); ,并将其分配给vm_故障结构 vmf->page = page; lddv3第15章也说明了这一点的后一部分。

    以这种方式使用mmap映射自定义设备驱动程序的内存,就我所知,可以像普通malloc的内存一样使用可能有一些方法可以使用DMA库获得类似的结果,但是我有一些限制来阻止该路由,或者将设备树节点与驱动程序相关联。