所谓的内存映射就是把物理内存映射到进程的地址空间之内,这些应用程序就可以直接使用输入输出的地址空间,从而提高读写的效率。Linux提供了mmap()函数,用来映射物理内存。
在驱动程序中,应用程序以设备文件为对象,调用mmap()函数,内核进行内存映射的准备工作,生成vm_area_struct结构体,然后调用设备驱动程序中定义的mmap函数。
2. 映射的种类
把同一个物理地址映射为虚拟地址有两种方法,第一种是mmap()函数将物理地址映射到进程的虚拟地址空间中去,第二种方法为ioremap()函数映射到内核虚拟地址上的方法。
mmap映射的方法:
有两种方法建立页表,一次性建立页表,可以调用函数remap_pfn_range和每次建立一个页的页表,调用函数nopage。
remap_pfn_range:
这个函数的功能是一次性建立新的页表去映射物理地址。
int remap_pfn_range(struct vma_area_struct* vma,unsigned long virt_addr,unsigned long pfn,unsigned long size,pgprot_t prot);
返回值:映射成功时返回0,否则返回一个错误的负数代码。
vma 物理地址被映射到的虚拟内存区域
virt_addr 被映射到用户空间的起始虚拟地址。页表建立的范围在virt_addr到virt_addr+size
pfn 对应物理地址的页框号,一般是vma->vm_pgoff域。
size 被映射区域的字节大小
prot vma->vm_page_prot
nopage:
struct page *(*nopage) (struct vm_area_struct *vma,unsigned long address,int *type);
vm_area_struct:虚拟内存区域
address:发生page fault的进程空间的虚拟地址
type 返回page fault可处理类型的地址
get_page(struct page* pageptr);
增加被映射页的引用次数。