1、内存映射主要是将用户空间的MMAP区域的虚拟地址空间映射到物理内存或者设备内存和IO空间
主要通过file_operation中的mmap来实现用户空间对设备内存的直接访问。
2、设备缓存与设备内存
设备缓存:驱动程序分配管理的一段物理内存,是主内存RAM中的一部分。
设备内存:是设备自带的存贮空间,是设备的一部分
设备缓存与设备内存之间通常采用DMA方式来传输数据。
3、用户空间MMAP区域
用户空间对MMAP区域的管理:
进程task_struct ----> mm_struct -----> mmap -----> struct vm_area_struct 双向链表。
4、struct vm_area_struct
作用:用来管理用户空间MMAP区域的结构体。
struct vm_area_struct {
struct mm_struct *vm_mm; //当前vm_area_struct对象所表示的虚拟地址空间段所归属的进程虚拟地址空间
unsigned long vm_start; //当前虚拟地址段的起始地址
unsigned long vm_end; //当前虚拟地址段的结束地址
struct vm_area_struct *vm_next , *vm_prev; //链表,将struct vm_area_struct对象组织成双向链表
pgprot_t vm_page_prot; //在进程映射时的页保护属性,主要体现在页目录表项的映射属性中
unsigned long vm_flags; //当前虚拟地址段的访问属性
const struct vm_operations_struct *vm_ops; //当前struct vm_area_struct对象上的一组操作集
---------------------
}
5、用户空间虚拟地址的布局
分为传统布局和新式布局
传统布局的MMAP区域是向上增长的,新式布局的MMAP区域是向下增长的。
6、mmap的调用过程
void *mmap(void *start, size_t length, int proc, int flags, int fd, off_t offset)
|
|--------> sys_mmap_pgoff(unsigned long addr ,unsigned long len, unsigned long prot, unsigned long flags, unsigned long fd, unsigned long pgoff)
|
|-------->do_mmap_pgoff(struct file *file, unsigned long addr, unsigned long len, unsigned long prot, unsigned long flags, unsigned long paoff)
|
|--------> get_unmaped_area 获得可用的MMAP区域的虚拟地址
|--------> mmap_region 将get_unmapped_area获得的地址构建一个struct vm_area_struct对象
|
| --------> file->f_op -> mmap(file, vma)
int (*mmap)(struct file *, struct vm_area_struct *);
驱动程序中的mmap所要做的工作是将内核分配的一个MMAP区域(通过struct vm_area_struct传递给mmap)通过页目录也页表操作,映射到相应的物理地址上去。
7、驱动程序中mmap的实现
内核为了方便mmap的实现,提供了两个函数:
a、 int remap_pfn_range(struct vm_area_struct *vma, unsigned long addr, unsigned long pfn unsigned long size, pgprot_t prot);
addr 虚拟地址的起始地址
size 地址空间大小
pfn 页框号
prot 映射时的页保护属性
remap_pfn_range把虚拟地址映射到pfn开始的一组连续的物理页面上。
b、io_remap_pfn_range
一般映射的目标地址是RAM或者是MM空间,使用 remap_pfn_range.
如果映射的目标地址是IO空间,则使用io_remap_pfn_range
8、munmap
不用驱动程序来实现。
munmap -----> sys_munmap ------> do_munmap