1.基础概念
mmap是一种内存映射文件的方式。即将一个文件或一块设备内存(如设备寄存器)映射到进程的地址空间,实现文件磁盘地址(or设备io地址)和进程虚拟地址空间(用户空间,非内核空间,ioremap函数才是向内核空间映射)中一段虚拟地址的一一对应的关系。
进程就在读写操作这段内存时,系统会自动回写脏页面到对应的文件磁盘上(或写入到设备地址空间),就完成了对文件/设备的操作,而不需要再调用read,write等系统调用函数。
这也意味着,内核空间和进程空间映射了相同的文件磁盘地址(or设备io地址),即内核空间对这段区域的修改也直接反映到用户空间,从而可以实现不同进程间的文件共享。
2.mmap原理
mmap函数创建一个新的vm_area_struct结构,并将其与文件/设备的物理地址相连。
vm_area_struct:
linux使用vm_area_struct来表示一个独立的虚拟内存区域,一个进程可以使用多个vm_area_struct来表示不用类型的虚拟内存区域(如堆,栈,代码段,MMAP区域等)。
vm_area_struct结构中包含了区域起始地址。同时也包含了一个vm_opt指针,其内部可引出所有针对这个区域可以使用的系统调用函数。从而,进程可以通过vm_area_struct获取操作这段内存区域所需的任何信息。
进程通过vma操作内存,而vma与文件/设备的物理地址相连,系统自动回写脏页面到对应的文件磁盘上(或写入到设备地址空间),实现内存映射文件。
内存映射文件的原理:
首先创建虚拟区间并完成地址映射,此时还没有将任何文件数据拷贝至主存。当进程发起读写操作时,会访问虚拟地址空间,通过查询页表,发现这段地址不在物理页上,因为只建立了地址映射,真正的数据还没有拷贝到内存,因此引发缺页异常。缺页异常经过一系列判断,确定无非法操作后,内核发起请求调页过程。最终会调用nopage函数把所缺的页从文件在磁盘里的地址拷贝到物理内存。之后进程便可以对这片主存进行读写,如果写操作修改了内容,一定时间后系统会自动回写脏页面到对应的磁盘地址,完成了写入到文件的过程。另外,也可以调用msync()来强制同步,这样所写的内存就能立刻保存到文件中。
参考:
https://blog.youkuaiyun.com/ddddfang/article/details/88943612