Linux内核page cache预读机制与读写性能调优 - 第1节

1.1 什么是 Page Cache

Page Cache(页缓存)是 Linux 内核中用于缓存磁盘文件数据的一种内存缓存机制。当应用程序读取文件时,内核会将磁盘上的数据块以页(通常为 4KB)为单位读入 Page Cache;后续对该文件同一区域的读操作将直接从内存返回,避免昂贵的磁盘 I/O。写操作同样先写入 Page Cache,再由内核异步刷回磁盘(写回策略),从而大幅提升文件 I/O 性能。

核心要点:Page Cache 的本质是“用内存换速度”——利用 DRAM 的纳秒级访问延迟掩盖磁盘的毫秒级延迟,是 Linux 存储性能优化的基石。

1.1.1 Page Cache 的关键特征

特征 说明
缓存粒度 以物理内存页(通常 4KB)为基本单位
缓存对象 磁盘文件的数据块、目录项、元数据(inode)
写策略 Write-back(写回):写入 Page Cache 即返回,脏页异步刷盘
替换策略 双链 LRU(最近最少使用):活跃链表 + 非活跃链表
生命周期 随文件打开而创建,随内存回收或文件关闭而释放
共享性 多个进程可共享同一文件的 Page Cache 页

1.2 Page Cache 在 Linux 存储栈中的位置

Linux 存储栈是一个分层架构,Page Cache 位于虚拟文件系统(VFS)与块设备层之间,是文件系统 I/O 路径上的核心缓存层。下图展示了 Page Cache 在存储栈中的精确位置:

Linux 存储栈架构 — Page Cache 位置 用户空间应用程序(User Applications) 系统调用层(read / write / mmap) 虚拟文件系统 VFS(Virtual File System) 具体文件系统(ext4 / XFS / Btrfs) Page Cache 层(页缓存 + 预读逻辑) 块设备层(Block Layer / I/O 调度器) 磁盘驱动程序(NVMe / SCSI / SATA) 物理磁盘 / SSD / NVMe 核心缓存层 性能关键路径
关键观察:Page Cache 位于文件系统与块设备层之间,所有文件 I/O(除 O_DIRECT 绕过外)均经过 Page Cache。这意味着 Page Cache 的命中率直接决定了应用程序的读写延迟。

1.2.1 读 I/O 路径中的 Page Cache

  1. 应用程序调用 read() → 陷入内核,进入 VFS 层。
  2. VFS 查找 dentry + inode → 确定文件对应的索引节点。
  3. Page Cache 查找 → 内核根据文件偏移量计算页索引,在 Page Cache 基数树(radix tree / xarray)中查找。
  4. Cache 命中 → 直接复制数据到用户缓冲区,返回(零磁盘 I/O)。
  5. Cache 未命中 → 触发缺页中断,分配新页,发起磁盘 I/O 读取数据,填入 Page Cache,再复制到用户缓冲区。

1.3 Page Cache 与虚拟内存的关系

Page Cache 与虚拟内存(Virtual Memory)共享同一套物理内存管理机制,两者在物理页层面完全统一。理解这种关系是掌握 Linux 内存与存储性能调优的前提。

1.3.1 物理页的统一管理

Linux 内核使用 struct page 描述每一个物理页帧。一个物理页要么属于某个进程的匿名页(堆、栈、数据段),要么属于 Page Cache(文件缓存页),两者通过同一套伙伴系统(Buddy Allocator)分配和回收。

Page Cache 与虚拟内存的物理页共享关系 物理内存池(Physical Memory — struct page 数组) 伙伴系统分配器(Buddy Allocator)统一管理所有物理页 匿名页(Anonymous Pages) 进程堆/栈/数据段 · 无文件背景 Page Cache 页(File-backed Pages) 文件数据缓存 · 有文件背景 关键关系:Page Cache 页与匿名页共享同一物理内存池,通过 LRU 链表竞争内存资源 内存压力下,内核同时回收两种页,Page Cache 优先被回收(因为可以重新从磁盘读取)

1.3.2 文件映射与 mmap

通过 mmap() 系统调用,进程可以将文件直接映射到其虚拟地址空间。此时,Page Cache 页同时出现在两个地方:

  • 内核的 Page Cache 基数树 — 全局文件缓存索引。
  • 进程的页表(Page Table) — 映射到进程虚拟地址空间的某个 VMA 区域。

这意味着同一个物理页被内核和进程“共享”,数据无需在用户态与内核态之间复制(零拷贝),这是 mmap 相比 read/write 性能优势的根本原因。

注意:mmap 虽然减少了数据拷贝,但引入了缺页异常(page fault)开销。对于随机小 I/O 场景,mmap 的缺页开销可能超过 read/write 的拷贝开销,需要根据实际负载选择。

1.3.3 脏页回写与内存回收

Page Cache 中的脏页(Dirty Pages)通过以下机制与虚拟内存子系统交互:

机制 触发条件 行为
pdflush / flusher 线程 脏页比例超过 dirty_background_ratio(默认 10%) 后台异步刷盘,不阻塞应用程序
同步回写 脏页比例超过 dirty_ratio(默认 20%) 阻塞写进程,强制刷盘直到比例下降
内存回收(kswapd) 空闲内存低于 pages_min 优先回收 Page Cache 中的干净页,脏页先刷盘再回收
直接回收(direct reclaim) 内存分配失败,kswapd 无法及时补充 分配路径直接回收 Page Cache,可能导致严重性能抖动

1.3.4 性能影响总结

Page Cache 与虚拟内存的关系对性能调优有直接指导意义:

  • Page Cache 占用过多内存 → 应用程序可用内存减少,可能触发 swap 或 OOM。
  • 内存回收压力大 → Page Cache 被频繁驱逐,缓存命中率下降,I/O 延迟飙升。
  • 脏页比例过高 → 写性能先快后慢,突发延迟抖动。
  • mmap 映射文件 → 减少拷贝但增加缺页,适合大文件顺序访问。
调优启示:监控 /proc/meminfo 中的 Cached、Dirty、Writeback 字段,结合 sar -B 的 pgpgin/pgpgout 指标,可以快速判断 Page Cache 是否成为性能瓶颈。后续章节将深入讲解如何通过 sysctl 参数(dirty_ratio、dirty_background_ratio、vfs_cache_pressure 等)进行精准调优。