reserve_virt_addr = ioremap(mem_start *1024 * 1024, mem_size *1024 * 1024); printk("reserve_virt_addr = 0x%lx\n", (unsigned long)reserve_virt_addr); if (reserve_virt_addr) { int i; for (i = 0; i < mem_size *1024 * 1024; i += 4) { reserve_virt_addr[i] = 'a'; reserve_virt_addr[i + 1] = 'b'; reserve_virt_addr[i + 2] = 'c'; reserve_virt_addr[i + 3] = 'd'; } } else { unregister_chrdev(major, "mmapdrv"); return - ENODEV; } return 0; }
/* remove the module */ void cleanup_module(void) { if (reserve_virt_addr) iounmap(reserve_virt_addr);
unregister_chrdev(major, "mmapdrv"); return ; }
int mmapdrv_open(struct inode *inode, struct file *file) { MOD_INC_USE_COUNT; return (0); }
int mmapdrv_release(struct inode *inode, struct file *file) { MOD_DEC_USE_COUNT; return (0); }
int mmapdrv_mmap(struct file *file, struct vm_area_struct *vma) { unsigned long offset = vma->vm_pgoff << PAGE_SHIFT; unsigned long size = vma->vm_end - vma->vm_start;
if (size > mem_size *1024 * 1024) { printk("size too big\n"); return ( - ENXIO); }
offset = offset + mem_start * 1024 * 1024;
/* we do not want to have this area swapped out, lock it */ vma->vm_flags |= VM_LOCKED; if (remap_page_range(vma, vma->vm_start, offset, size, PAGE_SHARED)) { printk("remap page range failed\n"); return - ENXIO; } return (0); }
|
remap_page_range函数的功能是构造用于映射一段物理地址的新页表,实现了内核空间与用户空间的映射,其原型如下:
int remap_page_range(vma_area_struct *vma, unsigned long from, unsigned long to, unsigned long size, pgprot_tprot); |
使用mmap最典型的例子是显示卡的驱动,将显存空间直接从内核映射到用户空间将可提供显存的读写效率。
-- 原文链接: http://dev.yesky.com/412/2639912.shtml
|