土法炼钢兴趣小组的算法知识备份

【操作系统百科】页缓存深入(VM 视角)

文章导航

分类入口
os
标签入口
#page-cache#folio#xarray#readahead#writeback#dirty-throttle

目录

页缓存(page cache)把磁盘文件内容缓存在内存——read/write/mmap 几乎都经过它。D-29 讲了 VM 模型;这里从 VM 视角深入:address_space 如何组织页、folio 改造、readahead 怎么决策、writeback 怎么限速。

一、先看图

flowchart LR
    READ[用户 read/mmap] --> AS[address_space<br/>XArray 索引]
    AS -->|hit| PAGE[folio<br/>在内存]
    AS -->|miss| RA[readahead 决策]
    RA --> BIO[submit_bio<br/>读盘]
    BIO --> PAGE
    WRITE[用户 write] --> PAGE
    PAGE -->|dirty| WB[writeback<br/>flush thread]
    WB --> DISK[磁盘]
    MEMCG[memcg 限制] -.限速.-> WB
    classDef sw fill:#388bfd22,stroke:#388bfd,color:#adbac7;
    classDef io fill:#f0883e22,stroke:#f0883e,color:#adbac7;
    class READ,WRITE,AS,PAGE,MEMCG sw
    class RA,BIO,WB,DISK io

二、address_space

每个 inode 有一个 address_spaceinode->i_mapping),管理此文件的所有缓存页。

struct address_space {
    struct inode *host;
    struct xarray i_pages;      // XArray 索引(原 radix tree)
    gfp_t gfp_mask;
    atomic_t i_mmap_writable;
    struct rb_root_cached i_mmap; // file-backed VMA rmap(interval tree)
    const struct address_space_operations *a_ops;
    ...
};

a_ops 包含 read_foliowritepagesdirty_folio 等回调——文件系统实现它们。

三、radix tree → XArray

5.x 以前用 radix tree(RADIX_TREE)索引页。Matthew Wilcox 主导改造成 XArray

6.x 内核里再看不到 radix_tree_lookup——全部变 xa_*

四、folio:告别 compound page 混乱

4.1 问题

THP 引入 compound page(head page + tail page),但旧 API 分不清”这个 struct page 到底是 head 还是 tail”,代码里充满 compound_head() 调用和 bug。

4.2 folio 方案

struct folio = “逻辑上的一整页(1 个或 2^n 个物理页)”。用 folio 就不会踩到 tail page。

struct folio {
    // 嵌入 struct page(head page)
    unsigned long flags;
    struct address_space *mapping;
    pgoff_t index;
    void *private;
    atomic_t _mapcount;
    atomic_t _refcount;
    unsigned int _nr_pages;    // 这个 folio 有几页
    ...
};

好处:

6.x 的 readahead、writeback、reclaim 路径基本 folio 化。

五、readahead

readahead 预读是减少 major fault 的核心:

5.1 算法

ondemand_readahead:检测顺序读模式,动态扩大 readahead window(初始 128KB → 最大 read_ahead_kb,默认 128KB-2MB)。

随机读 → readahead 关闭(只读当前页)。

5.2 触发

filemap_fault → do_async_mmap_readahead (触发异步预读)
generic_file_read_iter → filemap_read → page_cache_sync_readahead (同步读)

5.3 调优

cat /sys/block/sda/queue/read_ahead_kb   # 默认 128
echo 2048 > /sys/block/sda/queue/read_ahead_kb  # 大文件顺序读

# 或 per-file
posix_fadvise(fd, 0, 0, POSIX_FADV_SEQUENTIAL);   # 提示顺序
posix_fadvise(fd, 0, 0, POSIX_FADV_RANDOM);        # 关闭预读

六、writeback 与 dirty throttling

6.1 脏页限速

内核不允许脏页占太多内存——否则突然写盘卡住。balance_dirty_pages 在脏页比例超过阈值时开始”限速”写入进程。

两个阈值:

vm.dirty_ratio          = 20     # 全局脏页占可用内存 20% 时,进程同步等
vm.dirty_background_ratio = 10   # 10% 时唤醒 flush 线程后台写

6.2 flush 线程

kworker/u*:*+flush-*(workqueue flush):

6.3 memcg 交互

cgroup v2 的 memory.max 限制包含页缓存。memcg 内 dirty 页超限 → 触发本 cgroup 的 writeback。

memory.stat 里 file_dirty / file_writeback 看 cgroup 级脏页。

七、页缓存淘汰

见 D-36 详细讲;简述:

八、常见问题

A:大文件拷贝占满 RAM 正常——page cache 吃光闲置内存。回收机制保证压力时释放。如要避免:posix_fadvise(DONTNEED)dd iflag=direct

B:dirty page 积压导致延迟抖动 降低 vm.dirty_ratio / vm.dirty_background_ratio;或用 cgroup 限单个服务。

C:频繁 drop_caches echo 3 > /proc/sys/vm/drop_caches 丢掉所有 page cache——短暂降内存但之后 I/O 骤增。生产不推荐。

D:mmap 读大文件 vs read mmap 少一次 copy(零拷贝),但 page fault 开销 + mmap_lock 争抢。小文件/随机读 mmap 不占优。

九、观察

free -h                           # buff/cache 列
cat /proc/meminfo | grep -E 'Cached|Dirty|Writeback|AnonPages'
vmtouch /path/to/file             # 看特定文件缓存状态
sar -r 1                          # kbcached 列

# 脏页实时
watch -n1 grep -E 'Dirty|Writeback' /proc/meminfo

十、小结


参考文献

工具


上一篇缺页处理 下一篇内存回收

同主题继续阅读

把当前热点继续串成多页阅读,而不是停在单篇消费。

2026-05-16 · os

【操作系统百科】VFS I/O 路径全景

一次 read(fd, buf, n) 从用户态到磁盘要穿过多少层?本文追踪 VFS read/write 全路径——file_operations、iter_iov、iomap、页缓存命中与 miss、直接 I/O 旁路、块层提交、fsnotify 插桩。

2025-08-18 · storage

【存储工程】Page Cache 深度解析

应用程序每一次 read() 或 write() 系统调用,感觉像是直接在操作磁盘上的文件,但实际上,内核在中间插入了一层透明的缓存——页缓存(Page Cache)。这层缓存用物理内存保存最近访问过的文件数据,使得绝大多数读操作不需要触发磁盘 I/O,而写操作可以先落到内存,再由后台线程异步刷回存储设备。

2026-04-27 · os

【操作系统百科】内存回收

Linux 内存回收是 VM 最复杂的子系统之一。本文讲 active/inactive LRU、kswapd 与 direct reclaim、watermark 三线、swappiness 的真实含义、MGLRU 改造、memcg 回收与 PSI。

2026-04-28 · os

【操作系统百科】交换

swap 还值得开吗?本文讲 swap area 基础、swap cache、zram 压缩内存、zswap 前端压缩池、swappiness 的真实含义、容器里的 swap 策略,以及为什么现代 Android 全靠 zram 不靠磁盘。


By .