如果使用阶数大于1的__GET_FREE_PAGES(),如何创建VM_Area映射? [英] How to create vm_area mapping if using __get_free_pages() with order greater than 1?
问题描述
我正在DMA的设备驱动程序中重新实现mmap
。
我看到这个问题:Linux Driver: mmap() kernel buffer to userspace without using nopage有一个答案,使用vm_insert_page()
一次映射一个页面;因此,对于多个页面,需要在循环中执行。是否有其他API处理此问题?
之前,我使用dma_alloc_coherent
为DMA分配内存块,并使用remap_pfn_range
构建将进程的虚拟内存与物理内存相关联的页表。
__get_free_pages
分配更大的内存块,阶数大于1。在这种情况下,我不确定如何构建页表。原因如下:
我查看了Linux设备驱动程序一书,注意到以下内容:
背景:
当用户空间进程调用mmap将设备内存映射到其地址空间时,系统会创建一个新的VMA来表示该映射。支持mmap(从而实现mmap方法)的驱动程序需要通过完成该VMA的初始化来帮助该过程。
remap_pfn_range
的问题:
remap_pfn_range
不允许您重新映射常规地址,其中包括通过调用get_free_page
获得的地址。取而代之的是,它映射到零页面。除了进程看到的是私有的、填充为零的页面,而不是它希望看到的重新映射的RAM之外,一切似乎都正常。
序号为0的get_free_pages
对应的实现,即cullp设备驱动程序中只有1页:
如果分配顺序大于零,则对cullp设备禁用mmap方法,因为nopage处理单个页面,而不是页面集群。Cullp根本不知道如何正确管理属于更高级别分配的页面的引用计数。
我可以知道是否有方法为使用__get_free_pages
获得的阶数大于1的页面创建VMA?
我查看了Linux源代码,注意到有一些驱动程序重新实现了struct dma_map_ops->alloc()
和struct dma_map_ops->map_page()
。我可以知道这是不是正确的做法?
推荐答案
我想我的问题得到了答案。如果我错了,请随时纠正我。
我在谷歌搜索vm_insert_page
时,碰巧看到了这个补丁:mm: Introduce new vm_map_pages() and vm_map_pages_zero() API。
以前的驱动程序有自己的方法将内核页面/内存范围映射到用户vma,这是通过在循环中调用vm_ins_page()来完成的。
由于此模式在不同的驱动程序中是通用的,因此可以通过创建新函数并在所有驱动程序中使用它来进行泛化。
vm_map_ages()是可用于映射考虑了vm_pgoff的驱动程序中的内核内存/页面的API。
看过后,我知道我找到了我想要的。
该函数也可以在Linux Kernel Core API Documentation中找到。
remap_pfn_range()
和vm_insert_page()
之间的区别是,answer和vm_insert_page()
之间的区别是,answer对question非常有帮助,其中包含一个指向explanation by Linus的链接。
顺便提一句,这个补丁mm: Introduce new vm_insert_range and vm_insert_range_buggy API表明vm_map_pages()
的早期版本是vm_insert_range()
,但我们应该坚持vm_map_pages()
,因为在幕后vm_map_pages()
调用vm_insert_range()
。
这篇关于如果使用阶数大于1的__GET_FREE_PAGES(),如何创建VM_Area映射?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!