内存映射VMA
用户空间是不可能也不应该直接访问设备的,但是,设备驱动程序中可实现 mmap()函数,这个函数可使得用户空间能直接访问设备的物理地址。实际上,mmap()实现了这样的一个映射过程:它将用户空间的一段内存与设备内存关联,当用户访问用户空间的这段地址范围时,实际上转化为对设备的访问。mmap()必须以 P AGE_SIZE 为单位进行映射,实际上, 内存只能以页为单位进行映射, 若要映射非 P AGE_SIZE 整数倍的地址范围,要先进行页对齐, 强行以 P AGE_SIZE的倍数大小进行映射。
从内核看,进程是分配系统资源(CPU、内存)的载体,为了管理进程,内核必须对每个进程所做的事情进行清楚的描述,这就是进程描述符,内核用task_struct结构体来表示进程,并且维护一个该结构体链表来管理所有进程。该结构体包含一些进程状态、调度信息等上千个成员,我们这里主要关注进程描述符里面的内存描述符(struct mm_struct mm)
具体的结构,请参考下图
现在已经知道了内存映射是把设备地址映射到进程空间地址(注意:并不是所有内存映射都是映射到进程地址空间的,ioremap是映射到内核虚拟空间的,mmap是映射到进程虚拟地址的),实质上是分配了一个vm_area_struct结构体加入到进程的地址空间,也就是说,把设备地址映射到这个结构体,映射过程就是驱动程序要做的事了
过程用户空间mmap()->sys_mmap_pgoff()进入内核 —>do_mmap_pgoff()完成内存的映射(根据用户空间mmap函数的参数构成struct vm_area_struct 对象,然后调用filp->f_op->mmap函数)。
设备驱动程序中的mmap()函数,将内核提供的用户空间来自MMAP区域的一段内存(内核将这段区域以struct vm_area_struct 对象作为参数的方式告诉驱动程序)映射到设备内存上。驱动程序需要通过配置相应的页目录表项的方式来完成。
使用内核提供的函数来完成映射: remap_pfn_range(),
mmap主要有2种用法,一个是建立匿名映射,可以起到父子进程之间共享内存的作用。另一个是磁盘文件映射进程的虚拟地址空间(这个和交换分区的概念不同,交换分区的概念是基于页面置换的实现),可以节省一次内存拷贝.
https://www.cnblogs.com/wanghuaijun/p/7624564.html
浙公网安备 33010602011771号