在mmap函数里,使用
remap_pfn_range函数。代码如下。注意要设置一下vma->vm_pgoff为你要map的io空间的物理地址对应的页。
arm IO/ 内存统一编址 所以
#define io_remap_pfn_range(vma,from,pfn,size,prot) /
remap_pfn_range(vma, from, pfn, size, prot)
vm_start, vm_end 在系统调用时算好了,应该时找个空闲得空间,然后根据size算出vm_end,
static int filter_mmap(struct file *filp, struct vm_area_struct *vma)
{
vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
vma->vm_pgoff = ( (u32)map_start >> PAGE_SHIFT);
if (
remap_pfn_range(vma,
vma->vm_start,
vma->vm_pgoff,
vma->vm_end-vma->vm_start,
vma->vm_page_prot))
return -EAGAIN;
return 0;
}
map 过程 :
用户空间map(start,offset, len , fd ,...) start 映射到的用户空间地址,0就是自己去找吧,offset 文件的偏移。
old_mmap(struct mmap_arg_struct __user *arg) // arch/arm/kernel/sys_arm.c
|
do_mmap2(a.addr, a.len, a.prot, a.flags, a.fd, a.offset >> PAGE_SHIFT);
|
do_mmap_pgoff(file, addr, len, prot, flags, pgoff); // mm/mmap.c
可能合并VMA
否则新分配一个VMA
然后
error = file->f_op->mmap(file, vma);
就调用了驱动里的mmap
这时候vma->vm_pgoff = pgoff (这个pgoff就是map(offset, len , fd ,...) 中的 offset ,当然经过处理了,PAGE_SHIFT移来移去的)