Page Cache 缓存文件内容页面。读文件时先查询缓存,命中就直接复制给用户态;未命中才从存储读取并填入缓存。写文件时通常先修改缓存页并标记为脏页,后台回写再把它们批量落盘。它让很多小 I/O 合并为更高效的存储访问,但也让“write() 返回成功”与“数据已经安全落盘”成为两件事。

read/write 系统调用查询 Page Cache命中直接访问未命中读取磁盘脏页后台回写
缓存图读路径追求命中,写路径需要区分“进入缓存”和“持久化完成”。
address_space文件的页缓存索引,连接 inode、缓存页和回写操作。缓存命中用户读到内存中的数据,不需要等待底层设备。缺页读取文件系统和块层把所需数据读入缓存,再唤醒等待者。脏页write 修改后的缓存数据,尚未保证已到达持久介质。回写内核按阈值和时机把脏页提交给文件系统和设备。fsync请求把相关数据及必要元数据推进到持久化语义边界。

缓存命中快,不代表应用没有排队

一个文件读得很快,可能只是数据刚好还在内存中;第一次冷读、内存压力下被回收后的再读,以及多个任务争抢同一块存储,表现都会不同。性能分析要区分缓存命中率、读放大、队列等待和实际设备延迟,不能只用一次 cat 的时间得出结论。

预读会在顺序访问时提前填充后续页面,随机访问则更依赖工作集是否留得住。不同访问模式可通过 mmap、普通 read、预读提示等路径表现出来,选择之前应先测工作负载而不是为“零拷贝”或“缓存绕过”贴标签。

fsyncO_DIRECT 都有明确代价

fsync 用于需要更强持久化语义的场景,但频繁调用会增加提交压力。O_DIRECT 试图绕过页缓存,通常伴随地址、长度和偏移对齐要求,也可能与缓存读写交错造成一致性和性能问题。它们不是通用加速开关,应由数据丢失容忍度和真实 I/O 模式决定。

参考:Page Cache 与 Buffer Cache