Linux mmap:在用户空间映射使用 kmalloc 分配的内核缓冲区
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/6967933/
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
mmap: mapping in user space a kernel buffer allocated with kmalloc
提问by MirkoBanchi
Which is the correct way to map in an user space process a buffer allocated with kmalloc? Maybe i didn't understand memory mapping yet...I write a kernel module that allocs this buffer (for example 120 bytes) and i would read and write it in a user-space process. Obviously i created a char device and implemented a mmap
method in the file_operations
struct. My method is:
在用户空间进程中映射使用 kmalloc 分配的缓冲区的正确方法是什么?也许我还不了解内存映射……我写了一个内核模块来分配这个缓冲区(例如 120 字节),我会在用户空间进程中读取和写入它。显然我创建了一个字符设备并mmap
在file_operations
结构中实现了一个方法。我的方法是:
static int my_mmap(struct file *filp, struct vm_area_struct *vma)
{
//printk(KERN_INFO "Allocated virtual memory length = %d", vma->vm_end - vma->vm_start);
long unsigned int size = vma->vm_end - vma->vm_start;
if (remap_pfn_range(vma, vma->vm_start,
__pa(mem_area) >> PAGE_SHIFT, //what about vma->vm_pgoff?
size,
vma->vm_page_prot) < 0)
return -EAGAIN;
vma->vm_flags |= VM_LOCKED;
vma->vm_ops = &vmops;
vma->vm_flags |= VM_RESERVED;
my_vm_open(vma);
return 0;
}
where mem_area
points at a memory area allocated with kmalloc
at module init. The area is filled with the same value (for example 0x10). All works but i think there is something wrong in this code:
wheremem_area
指向用kmalloc
at 模块 init分配的内存区域。该区域填充有相同的值(例如 0x10)。一切正常,但我认为这段代码有问题:
kmalloc
could return a pointer that isn't page aligned and, in that case, i don't think is correct the value of the third parameter ofremap_pfn_range
in fact in user space i read the wrong value. Instead all works if i use__get_free_page
(because the the function always returns a pointer that is page aligned) or whenkmalloc
returns a page aligned pointer. Memory mapping works with memory regions that are multple ofPAGE_SIZE
so, should i allocate an entire page instead of usingkmalloc
?When
my_mmap
is called, the kernel has allocated some pages yet? I ask this because i found some implementations of custommmap
method that callremap_pfn_range
withvma->vm_pgoff
as third parameter...how could be useful this? Is this the page frame of the first new allocated page? If i pass as third parameter a page frame like i do inmy_mmap
, i should free pages starting from page invma->vm_pgoff
?However i found an implementation of
mmap
method that maps a buffer allocated withkmalloc
. To correctly map the buffer an operation (that i don't undestand for now) is performed beforeremap_pfn_range
. Suppose thatmem
is the pointer returned bykmalloc
,mem_area
is initialized in this manner:mem_area=(int *)(((unsigned long)mem + PAGE_SIZE - 1) & PAGE_MASK);
kmalloc
可能会返回一个不是页面对齐的指针,在这种情况下,我认为remap_pfn_range
实际上在用户空间中我读取了错误的值的第三个参数的值是不正确的。相反,如果我使用__get_free_page
(因为该函数总是kmalloc
返回一个页面对齐的指针)或者当返回一个页面对齐的指针时,所有的工作。内存映射适用于多个这样的内存区域,PAGE_SIZE
我应该分配整个页面而不是使用kmalloc
吗?什么时候
my_mmap
调用,内核已经分配了一些页面了吗?我问这个是因为我发现了一些使用第三个参数mmap
调用的自定义方法的实现......这有什么用?这是第一个新分配页的页框吗?如果我像 in 一样将页面框架作为第三个参数传递,我应该从 page in 开始释放页面吗?remap_pfn_range
vma->vm_pgoff
my_mmap
vma->vm_pgoff
但是我找到了一个
mmap
方法的实现,它映射了一个分配有kmalloc
. 为了正确映射缓冲区,在remap_pfn_range
. 假设mem
是通过返回的指针kmalloc
,mem_area
以这种方式被初始化:mem_area=(int *)(((unsigned long)mem + PAGE_SIZE - 1) & PAGE_MASK);
So mem_area
contains the same value of mem
only if mem
is page aligned otherwise is should contain the pointer at the beginning of the next page. However, with this operation if i pass as third param of remap_pfn_range
the value __pa(mem_area) >> PAGE_SHIFT
mapping works well. Why?
因此mem_area
,mem
仅当mem
页面对齐时才包含相同的值,否则应该包含下一页开头的指针。但是,如果我作为remap_pfn_range
值__pa(mem_area) >> PAGE_SHIFT
映射的第三个参数传递,则使用此操作效果很好。为什么?
Thank you all!
谢谢你们!
回答by caf
Yes, you should be allocating a whole number of pages.
No, the kernel hasn't allocated any pages.
vm->vm_pgoff
is the requested offset within the device being mapped - it's the last parameter to the userspacemmap()
call, translated from bytes to pages. You're probably looking at themem
orkmem
mmap implementations, in which case the offset represents the physical or linear page that userspace wants to map.That is just allocating a page-aligned buffer within the
kmalloc()
allocated buffer. You're better off using__get_free_pages()
as you've already surmised, cutting out the middle-man.
是的,您应该分配整数页。
不,内核没有分配任何页面。
vm->vm_pgoff
是被映射的设备中请求的偏移量 - 它是用户空间mmap()
调用的最后一个参数,从字节转换为页面。您可能正在查看mem
或kmem
mmap 实现,在这种情况下,偏移量表示用户空间想要映射的物理或线性页面。这只是在
kmalloc()
分配的缓冲区中分配一个页面对齐的缓冲区。你最好使用__get_free_pages()
你已经猜到的,去掉中间人。
You should be testing that the size being mapped does not exceed your buffer.
您应该测试映射的大小是否不超过您的缓冲区。