页缓存与写回机制与实现详解

页缓存与写回机制与实现详解

源码路径rk3588/kernel-6.1/mm/filemap.creadahead.cpage-writeback.cbacking-dev.ctruncate.c
内核版本:Linux 6.1(RK3588)
文档目录linuxDoc/mm/


目录


一、原理

1.1 Page Cache 角色

页缓存缓存 文件数据 的物理页,使:

  • 读:优先内存命中,减少块设备 I/O
  • 写:先改缓存页,异步 写回(writeback) 到存储
  • mmap:文件映射直接 fault 到 cache 中的 folio

同一文件 inode 对应 struct address_space,其 i_pages(xarray)索引 offset → folio。

1.2 Folio(Linux 6.1)

folio 表示一个或多个连续 page 的缓存单元(尤其 THP、大块 I/O),filemap.c 路径以 folio 为中心,legacy API 经 folio-compat.c 适配。

1.3 预读(Readahead)

顺序读检测 访问模式,提前将后续页读入 cache,隐藏磁盘延迟。

1.4 写回与脏页

修改 mapped 或 write() 路径使页 置脏pdflush/bdi writeback 线程在脏页比例或 sync 时写回设备。

backing_dev 限制每设备的 inflight 写与脏页占比,防止内存被脏页占满。


二、实现方式

2.1 文件映射缺页:filemap_fault()

filemap.c ~3191:

  1. 根据 vmf->pgoffmapping->i_pages 查找 folio
  2. 未命中:pagecache_get_read / filemap_read_folio 读盘
  3. 可能 lock_page,返回 VM_FAULT_RETRY
  4. 安装 PTE,folio_mark_accessed

__handle_mm_fault 中文件 VMA 的 vm_ops->fault 衔接。

2.2 缓冲读:filemap_read / generic_file_read_iter

  • 按 offset 查找或分配 cache folio
  • 未 uptodate 则提交 bio 读盘
  • 拷贝到用户 iov

2.3 预读:readahead.c

  • page_cache_sync_readahead / ondemand_readahead
  • 根据 file->f_rastruct file_ra_state)维护预读窗口
  • readahead_expand 扩大窗口;force_page_cache_ra 强制预读

2.4 脏页与写回:page-writeback.c

步骤 说明
置脏 folio_mark_dirty__mark_inode_dirty
聚合 inode 挂到 bdi->wb 链表
写回 wb_writeback / write_cache_pages
完成 folio_end_writeback,清除 dirty

balance_dirty_pages:进程写超过 dirty_ratio 时节流。

2.5 backing-dev.c

每个块设备/文件系统注册 struct backing_dev_info

  • max_ratiodirty_bandwidth
  • cgroup writeback 关联(CONFIG_CGROUP_WRITEBACK

2.6 truncate.c

文件缩小或删除时 truncate_inode_pages:从 xarray 摘除 folio,若映射存在则通过 rmap unmap(见 06 文档)。

2.7 workingset 交互

频繁回收的 cache 页 refault 由 workingset.c 统计,影响 vmscan 对文件页的回收积极性(见 07 文档)。


三、关键数据结构与接口

结构/API 说明
struct address_space i_pages、host inode、a_ops
filemap_fault mmap 读 fault
filemap_read 缓冲读
folio_mark_dirty 标脏
sync(2) / fsync 触发写回

a_ops 常用read_foliowritepagesdirty_foliomigrate_folio


四、RK3588 平台说明

  • 编解码 读配置文件/码流 走 page cache;大文件顺序读可调 fadvise(SEQ)fadvise.c)。
  • dmabuf / GEM 不一定经过传统 page cache,但 VFS 层媒体仍可能用 shmem(见 12 文档)。
  • eMMC/UFS 慢时 dirty 内存高 会触发回收与写回竞争,表现为编码卡顿与 NR_WRITEBACK 升高。

五、调试与观测

手段 说明
/proc/meminfo Cached/Dirty/Writeback 缓存与写回量
echo w > /proc/sys/vm/drop_caches 丢弃 cache(调试用)
fiemap / sync 写回行为

trace:filemap tracepoints。


附录:源码索引

主题 文件 约略行号
filemap_fault filemap.c 3191
readahead readahead.c 全文
writeback page-writeback.c 全文
backing dev backing-dev.c 全文

文章互动

阅读 --

留言

0 条留言

正在加载留言…