linux 驱动mmap操作

VMA和PAGE结构 和mmap函数(关键在最后)
 
1.page  主要成员
 。。。//查源码
 
2.vm_area_struct  主要成员
。。。//查源码
 
3.mmap用户空间调用与内核空间调用
void *mmap(void *start,size_t length,int prot,int flags,int fd,off_t offset);

 //看man mmap

内核空间调用

int (*mmap) (struct file *filp, struct vm_area_struct *vma);

 

4.mmap执行的顺序
      a.在用户进程创建一个vma区域
      b.驱动程序获得页
      c.将获得的页分配给vma区域

四、如何给VMA分配页

    1.一次完成全部
int remap_pfn_range(struct vm_area_struct *vma, unsigned long virt_addr, unsigned long pfn, unsigned long size, pgprot_t prot); 
//vma 用户进程创建一个vma区域
//virt_addr 重新映射应当开始的用户虚拟地址. 这个函数建立页表为这个虚拟地址范围从 virt_addr 到 virt_addr_size.
//pfn 页帧号, 对应虚拟地址应当被映射的物理地址. 这个页帧号简单地是物理地址右移 PAGE_SHIFT 位. 对大部分使用, VMA 结构的 vm_paoff 成员正好包含你需要的值. 这个函数影响物理地址从 (pfn<<PAGE_SHIFT) 到 (pfn<<PAGE_SHIFT)+size.
//size 正在被重新映射的区的大小, 以字节.
//prot 给新 VMA 要求的"protection". 驱动可(并且应当)使用在vma->vm_page_prot 中找到的值.
//返回的值常常是 0 或者一个负的错误值

int io_remap_page_range(struct vm_area_struct *vma, unsigned long virt_addr, unsigned long phys_addr, unsigned long size, pgprot_t prot); 
//当用在 phys_addr 指向 I/O 内存时返回的值常常是 0 或者一个负的错误值???

2.一页一页的分配

struct page *(*nopage)(struct vm_area_struct *vma, unsigned long address, int *type);
//address 代表从用户空间传过来的用户空间虚拟地址
//返回一个有效映射页

 3.限制: 
remap_pfn_range不能映射常规内存,只存取保留页和在物理内存顶之上的物理地址。因为保留页和在物理内存顶之上的物理地址内存管理系统的各个子模块管理不到。640 KB 和 1MB 是保留页可能映射,设备I/O内存也可以映射如果想把kmalloc()申请的内存映射到用户空间,则可以通过mem_map_reserve()把相应的内存设置为保留后就可以。
remap_pfn_range常用于设备内存映射,而nopage()常用于RAM映射
posted @ 2012-03-07 17:12  Jack204  阅读(2438)  评论(0编辑  收藏  举报