Mir*_*chi 11 linux mmap linux-device-driver linux-kernel
在用户空间进程中映射使用kmalloc分配的缓冲区的正确方法是什么?也许我还没有理解内存映射......我编写了一个内核模块来分配这个缓冲区(例如120字节),我会在用户空间进程中读取和写入它.显然我创建了一个char设备并mmap在file_operationsstruct中实现了一个方法.我的方法是:
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;
}
Run Code Online (Sandbox Code Playgroud)
其中,mem_area在与分配的内存区域指向kmalloc在模块初始化.该区域填充相同的值(例如0x10).一切正常,但我认为这段代码有问题:
kmalloc可以返回一个非页面对齐的指针,在这种情况下,我认为不正确的第三个参数的值remap_pfn_range实际上在用户空间中我读错了值.相反,如果我使用__get_free_page(因为该函数总是返回kmalloc页面对齐的指针)或返回页面对齐指针时所有工作.内存映射适用于多个内存区域PAGE_SIZE,如果我分配整个页面而不是使用kmalloc?
什么时候my_mmap调用,内核已经分配了一些页面呢?我问这个,因为我发现定制的一些实现mmap调用方法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);
Run Code Online (Sandbox Code Playgroud)因此mem_area,mem仅当mem页面对齐时才包含相同的值,否则应包含下一页开头的指针.但是,如果我通过此操作,remap_pfn_range则值__pa(mem_area) >> PAGE_SHIFT映射的第三个参数效果很好.为什么?
谢谢你们!
是的,您应该分配一定数量的页面.
不,内核没有分配任何页面. vm->vm_pgoff是被映射的设备中请求的偏移量 - 它是用户空间mmap()调用的最后一个参数,从字节转换为页面.您可能正在查看mem或kmemmmap实现,在这种情况下,offset表示用户空间要映射的物理或线性页面.
这只是在kmalloc()分配的缓冲区中分配页面对齐的缓冲区.你__get_free_pages()已经猜测过你最好不要使用,切断了中间人.
您应该测试所映射的大小是否超过您的缓冲区.
| 归档时间: |
|
| 查看次数: |
11662 次 |
| 最近记录: |