C语言 vm_insert_page()和remap_pfn_range()有什么区别?

soat7uwm  于 2023-03-29  发布在  其他
关注(0)|答案(3)|浏览(214)

我想使用ioremap_wc()将设备内存(NIC)Map到内核空间内存区域。然后我想将内存区域从内核空间重新Map到用户空间,我可以使用2个函数:vm_insert_page()remap_pfn_range()
POSIX mmap(3)通常使用第二个:remap_pfn_range()
vm_insert_page()remap_pfn_range()有什么区别,什么时候需要使用vm_insert_page()而不是remap_pfn_range()

ohfgkhjo

ohfgkhjo1#

正如其名称所示,vm_insert_page()Map单个页面,而remap_pfn_range()Map连续的内核内存块
例如,可以使用vm_insert_pageMapvmalloc区域

do {
    page = vmalloc_to_page(vaddr);
    vm_insert_page(vma, uaddr, page);
    vaddr += PAGE_SIZE;
} while(/* there is something to map */);

使用remap_pfn_range是不可能的,因为它只Map内核内存的连续块。
另一个区别是,使用remap_pfn_range,您不仅可以MapRAM缓冲区,还可以Map其他范围。
Linus的explanation

gg0vcinb

gg0vcinb2#

vm_insert_page()允许驱动程序将它们分配的单独页面插入到用户vma中。页面必须在内核中独立分配。它要求页面是为此目的获得的零阶分配。它不会发出警告,也不要求设置PG_reserved。
传统上,这是用remap_pfn_range()来完成的,它接受一个任意的页面保护参数。vm_insert_page()不允许这样。你的vma保护必须正确设置,这意味着如果你想要一个共享的可写Map,你最好请求一个共享的可写Map!
remap_pfn_range()用于将一组页面Map或重新Map到存储器中。
Refer

nwlls2ji

nwlls2ji3#

总结如下:
当您不需要struct page作为物理页帧时,使用remap_pfn_range。对于需要struct page作为物理页帧的内存,使用vm_insert_page。(请注意,还有vm_insert_pages,它可以将多个页面插入VMA。)
对于来自此区域的直接I/O,请使用vm_insert_page/vm_insert_pages,因为它们支持get_user_page以获得struct page,这是后续ext4/scatterlist代码所必需的。

相关问题