在实现驱动程序的mmap函数时,要注意映射地址的转换问题,见代码。
定义一个设备结构体:
- struct leedriver
- {
- struct cdev cdev;
- unsigned char mem[MEMSIZE];
- };
这里面这个MEMSIZE,最小都要是4096,因为内存映射是以页为单位的。
在实现simple_remap_mmap函数时,代码如下
- static int simple_remap_mmap(struct file *filp, struct vm_area_struct *vma)
- {
- vma->vm_pgoff = ((u32)virt_to_phys(leedriverp->mem)) >> PAGE_SHIFT;
- printk("vma->vm_pgoff = %lx/n",vma->vm_pgoff);
- if (remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff,
- vma->vm_end - vma->vm_start,
- vma->vm_page_prot))
- return -EAGAIN;
- vma->vm_ops = &simple_remap_vm_ops;
- simple_vma_open(vma);
- return 0;
- }
注意函数开头的vma->vm_pgoff = ((u32)virt_to_phys(leedriverp->mem)) >> PAGE_SHIFT;
leedriverp->mem是个内核虚拟地址,应该通过virt_to_phys转换成物理地址,再进行左移操作,就OK了。
之后定义一下vm_ops
- static struct vm_operations_struct simple_remap_vm_ops = {
- .open = simple_vma_open,
- .close = simple_vma_close,
- };
并且在file_operations中添加.mmap=simple_remap_mmap,整个过程就完成了