前言
系统mmu开启后, 程序对内存的访问都是虚拟地址, 之后mmu会自动将虚拟地址变为实际的物理地址(硬件行为), 所以我们的程序如果要访问物理地址的话,必须要通过mmu建立虚拟地址与物理地址之间的映射关系。对于虚拟地址映射到物理地址的操作, 涉及到3个典型的函数.
- ioremap
- 在driver中使用,一般用于映射registers address。
- vmalloc
- 在dirver中使用,在内存的vmalloc区申请一块连续的虚拟空间,生成虚拟空间所对应的物理地址并非连续。
- mmap
- 在应用层使用,在应用层可以访问物理地址
上述阐述了使用场景,同样都是虚拟地址映射到物理地址,它们之间有什么区别呢? 这个问题必须要了解它们的实现才能明白,我们并不打算详细的分析代码,而是给出大体关键的脉络来分析这个问题。
ioremap 与 vmalloc
这两个函数之所以放在一起讲,是因为它们的实现几乎是一样的。
这两个函数都是从VMALLOC区(内核虚拟地址空间)分配虚拟地址空间(※注意是虚拟地址空间), 我们看张图来理解一下函数的实现
首先,VMALLOC区 是由两个结构体维护的,即:struct vmap_area和 struct vm_struct。
其中vmap_area是专门用来管理 VMALLOC区域的虚拟空间。
即,一个vmap_area结构代表一块有效的虚拟空间,
mmap
mmap在user层使用,user层可访问物理地址就用mmap.
- 从上图可知,应用层的mm结构维护这个进程的虚拟空间,这个虚拟空间每块合法的地址(虚拟地址)用vm_area_struct结构体来维护。
- mmap 会创建一个vma(vm_area_struct结构体),此vma中的虚拟地址变量必须在 3G空间中并且与其他vma结构体所维护的地址不发生冲突
- 申请好一个vma后,传给driver
- error = file->f_op->mmap(file, vma);
- driver在根据具体的情况来进行mmu映射