1.开场白
环境:
处理器架构:arm64
内核源码:linux-5.10.50
ubuntu版本:20.04.1
代码阅读工具:vim+ctags+cscope
Linux内核由于存在page cache, 一般修改的文件数据并不会马上同步到磁盘,会缓存在内存的page cache中,我们把这种和磁盘数据不一致的页称为脏页,脏页会在合适的时机同步到磁盘。为了回写page cache中的脏页,需要标记页为脏。
脏页跟踪是指内核如何在合适的时机记录文件页为脏,以便内核在进行脏页回写时,知道将哪些页面回写到磁盘。匿名页不需要跟踪脏页,因为不需要同步到磁盘;私有文件页也不需要跟踪脏页,因为映射的时候,可写页会映射为只读,写访问会发生写时复制,转变为匿名页;所以只有共享的文件页需要跟踪脏页。跟踪有两个层面:一个是页表项记录,一个是页描述符记录。
访问文件页有两种方式:一种是通过mmap映射文件,一种是通过文件系统的write接口操作文件,本文将对这两种方式进行讲解。在Linux内核中,因为跟踪脏页会涉及到文件回写、缺页异常、反向映射等技术,所以本文也重点讲解在Linux内核中如何跟踪脏页。
2.mmap映射的文件页
基本过程如下:
1)通过mmap映射共享文件。
2)第一次访问文件页时,发生缺页后读文件页到page cache, 如果是写访问则设置相应进程的页表项为脏、可写。
3)脏页回写时,会通过反向映射机制,查找映射这个页的每一个vma, 设置相应进程的页表项为只读,清脏标记。
4)假如第二次写访问这个文件页时,脏页的处理有两种情况:
-
page cache中的文件页还未回写到磁盘(3步骤之前), 此刻,这个文件页依然是脏页。因为相应进程的页表项为脏、可写,所以可以直接写这个页。
-
page cache中的文件页已经回写到磁盘(3步骤之后), 此刻,这个文件页不再是脏页。因为页表项为只读,所以写访问会发生写时复制缺页异常,异常处理中将处理共享文件页映射,重新将相应进程的页表项为设置为脏、可写。
分析如下: