如何将 Linux 内核缓冲区映射到用户空间?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/10760479/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to mmap a Linux kernel buffer to user space?
提问by ravi
Let's say the buffer is allocated using a page based scheme. One way to implement mmap would be to use remap_pfn_range but LDD3 says this does not work for conventional memory. It appears we can work around this by marking the page(s) reserved using SetPageReserved so that it gets locked in memory. But isn't all kernel memory already non-swappable i.e. already reserved? Why the need to set the reserved bit explicitly?
假设缓冲区是使用基于页面的方案分配的。实现 mmap 的一种方法是使用 remap_pfn_range 但 LDD3 表示这不适用于传统内存。看来我们可以通过使用 SetPageReserved 标记保留的页面来解决这个问题,以便它被锁定在内存中。但是不是所有的内核内存都已经不可交换,即已经保留了吗?为什么需要显式设置保留位?
Does this have something to do with pages allocated from HIGH_MEM?
这与从 HIGH_MEM 分配的页面有关吗?
采纳答案by Roland
The simplest way to map a set of pages from the kernel in your mmap method is to use the fault handler to map the pages. Basically you end up with something like:
在 mmap 方法中从内核映射一组页面的最简单方法是使用错误处理程序来映射页面。基本上你最终会得到类似的东西:
static int my_mmap(struct file *filp, struct vm_area_struct *vma)
{
vma->vm_ops = &my_vm_ops;
return 0;
}
static const struct file_operations my_fops = {
.owner = THIS_MODULE,
.open = nonseekable_open,
.mmap = my_mmap,
.llseek = no_llseek,
};
(where the other file operations are whatever your module needs). Also in my_mmap
you do whatever range checking etc. is needed to validate the mmap parameters.
(其他文件操作是您的模块需要的任何内容)。此外,my_mmap
您还需要进行任何范围检查等来验证 mmap 参数。
Then the vm_ops
look like:
然后vm_ops
看起来像:
static int my_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
{
vmf->page = my_page_at_index(vmf->pgoff);
get_page(vmf->page);
return 0;
}
static const struct vm_operations_struct my_vm_ops = {
.fault = my_fault
}
where you just need to figure out for a given vma / vmf passed to your fault function which page to map into userspace. This depends on exactly how your module works. For example, if you did
您只需要找出传递给故障函数的给定 vma / vmf 将哪个页面映射到用户空间。这完全取决于您的模块的工作方式。例如,如果你做了
my_buf = vmalloc_user(MY_BUF_SIZE);
then the page you use would be something like
那么您使用的页面将类似于
vmalloc_to_page(my_buf + (vmf->pgoff << PAGE_SHIFT));
But you could easily create an array and allocate a page for each entry, use kmalloc, whatever.
但是您可以轻松地创建一个数组并为每个条目分配一个页面,使用 kmalloc 等等。
[just noticed that my_fault
is a slightly amusing name for a function]
[刚刚注意到这my_fault
是一个有点有趣的函数名称]
回答by heptanesia
Though the pages are reserved via a kernel driver, it is meant to be accessed via user space. As a result, the PTE (page table entries) do not know if the pfn belongs to user space or kernel space (even though they are allocated via kernel driver).
虽然页面是通过内核驱动程序保留的,但它旨在通过用户空间访问。结果,PTE(页表条目)不知道 pfn 是属于用户空间还是内核空间(即使它们是通过内核驱动程序分配的)。
This is why they are marked with SetPageReserved
.
这就是它们标有 的原因SetPageReserved
。