在之前的公众号文章中,我们介绍过File cache的定义,其读流程及写流程,想了解上篇详情的可阅读:Linux内核File cache机制(上篇)
本篇则接上篇,主要介绍Linux mmap读文件流程涉及缺页中断。
一、mmap及缺页中断读文件流程分析
上面篇幅,“什么是Filecache”篇幅介绍了文件缓存框架,走读了read()流程中涉及文件缓存的操作流程。对于用户来说,读过程一般是同步读的过程(当然也有异步读的接口,其思想跟文件缓存异步预读机制类同,不再阐述),其执行完接口调用后所需数据就已经在内存中了,而操作的时候就通过write()等接口进行读写。
除了以上的接口,文件缓存的读取和使用是否还有其他方法?答案是肯定的,例如mmap()等接口可以实现将文件映射到用户地址空间,进程可以像访问普通内存一样对文件进行访问。mmap接口从内核的归属上是内存接口,Linux系统对于用户内存分配总是苛刻的,当用户分配内存时,内核优先只给虚拟内存(MAP_POPULATE等模式本文不作讨论),只有使用时才分配物理内存,通过mmap接口进行文件映射属于内核内存的管理框架内,自然也符合这个管理思想。
那么系统怎么及时地给用户分配物理内存呢?这里就引出缺页中断的概念:
当用户访问虚拟地址时发现地址没有映射到具体的物理内存空间,则触发中断进入内核态,进行物理内存填充,本文只关注文件页面的缺页中断。
对于文件缓存的缺页中断,另外一种触发的场景也非常常见:文件缓存因为内存紧张被系统回收了,因为回收的过程会进行虚拟内存解映射,此时用户再次访问到之前分配的虚拟地址时,同样也需要进入缺页中断流程进行数据的填充。关于文件缓存的回收,放到“Filecache 回收流程分析”章节,读者有兴趣可以进行查阅。
本篇幅通过分析mmap/munmap调用执行流程和文件缓存的缺页中断流程,了解该路径下文件缓存的读取过程。
1. mmap函数生命周期
mmap系统调用用于将用户空间的一端内存区域映射到内核空间,根据传递参数的不同,其可以实现共享内存、单独分配匿名内存以及映射文件页面等。本文主要阐述映射文件缓存,普通文件被映射到进程地址空间后,进程可以像访问普通内存一样对文件进行访问,而不需要调用read()/write()接口。
addr:是否指定映射的内存区域