vm_insert_page()和remap_pfn_range()有什么区别?

问题描述 投票:0回答:3

我想使用

ioremap_wc()
将设备内存(NIC)映射到内核空间内存区域。然后我想将内存区域从内核空间重新映射到用户空间,为此我可以使用 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()

c linux-kernel posix linux-device-driver mmap
3个回答
4
投票

顾名思义,

vm_insert_page()
映射一个单页,而
remap_pfn_range()
映射一个连续的内核内存块。检查原型和注释vm_insert_page, remap_pfn_range

例如可以使用

vm_insert_page
来映射
vmalloc
区域

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

使用

remap_pfn_range
是不可能的,因为它只映射一个连续的内核内存块。

另一个区别是使用

remap_pfn_range
你不仅可以映射RAM缓冲区,还可以映射其他范围。使用
vm_inser_page
你可以只映射 RAM 缓冲区

Linus 的解释


4
投票

vm_insert_page()
允许驱动程序将他们分配的单个页面插入到用户 vma 中。该页面必须在内核中独立分配。它要求页面是为此目的获得的零序分配。它不会发出警告,也不需要设置 PG_reserved。

传统上,这是通过

remap_pfn_range()
完成的,它采用任意页面保护参数。
vm_insert_page()
不允许这样。你的 vma 保护必须正确设置,这意味着如果你想要一个共享的可写映射,你最好要求一个共享的可写映射!

remap_pfn_range()
用于将一组页面映射或重新映射到内存中。

参考


1
投票

总结:

当您不需要

remap_pfn_range
作为物理页面框架时,请使用
struct page
。 使用
vm_insert_page
用于物理页面框架需要
struct page
的内存。 (请注意,还有 vm_insert_pages,它可以将多个页面插入 VMA。)

对于来自该区域的直接 I/O,使用

vm_insert_page/vm_insert_pages
,因为它们支持
get_user_page
以获得
struct page
,这是后续
ext4/scatterlist
代码所必需的。

© www.soinside.com 2019 - 2024. All rights reserved.