当前位置:首页>Linux>六年未竟的承诺:Linux 内核为何决定移除只读文件页缓存 THP?

六年未竟的承诺:Linux 内核为何决定移除只读文件页缓存 THP?

  • 2026-10-11 08:32:33
六年未竟的承诺:Linux 内核为何决定移除只读文件页缓存 THP?

摘要

2019 年,Linux 内核引入了针对页缓存(Page Cache)的只读透明大页(Read-only Transparent Huge Pages, THP)支持,并承诺未来几个版本内补齐可写支持。然而六年过去,这项“实验性功能”不仅没有扩展,反而即将被彻底移除。原因并不只是开发延期,而是内核内存管理体系本身已经发生根本演进——Folio(页簇)机制崛起,正在替代旧有 THP 拼接方案。这场改动不仅关乎一个配置项的去留,更揭示了 Linux 内核设计哲学的深层转变:从“补丁式增强”走向“原生结构升级”。本文将带你理解这场变革背后的技术逻辑,以及它对文件系统、页缓存与性能优化的深远影响。


六年后被删除的功能:只读文件页缓存 THP 的谢幕

有些内核特性,并不会按照最初设想的发展。

2019 年,开发者 Song Liu 为 Linux 内核引入了一个新能力:支持为页缓存创建只读透明大页(Transparent Huge Pages, THP)。当时他在 Kconfig 中留下了一句承诺——未来几个版本会支持可写大页。

六年后,这句承诺仍然挂在那里,但它永远不会实现了。因为这项功能即将被移除。

不是因为它失败了,而是因为内核底层已经换了“玩法”。


一、THP 是什么?为什么文件页缓存也想要它?

1.1 THP:透明大页机制

透明大页(THP)会自动将多个基础页(Base Page)聚合成更大的页块。

在 Intel 平台上,默认基础页大小是 4KB,而一个 THP 通常是:

512 X 4KB = 2M

这样做的好处是:

  • • 减少页表项数量
  • • 降低内存管理开销
  • • 提升 CPU 的 TLB(Translation Lookaside Buffer,地址转换后备缓冲区) 命中率

简单说,大页让 CPU 少翻“地址字典”。


1.2 为什么页缓存也需要 THP?

最初 THP 只支持匿名页(Anonymous Memory),例如程序堆、栈。

但文件映射内存(File-backed Memory)同样受益:

  • • 可执行文件代码段
  • • 共享库映射
  • • 文件缓存页

这些区域如果能合并成大页,同样可以减少 TLB 压力。

问题在于——页缓存最初根本不理解“大页”概念。


二、2019 年的方案:绕过 Page Cache 的“后门合并”

Song Liu 的方案并没有真正改造页缓存,而是借助后台线程 khugepaged 来偷偷完成合并。


2.1 khugepaged 的职责

/* mm/khugepaged.c */staticintkhugepaged(void *none){while (!kthread_should_stop()) {        khugepaged_do_scan();        schedule_timeout_interruptible(...);    }}

它会在后台扫描内存,把连续基础页合并成 THP。

2019 年的改动,让它也能处理文件页。


2.2 为什么只能“只读”?

因为写入 THP 会带来复杂一致性问题:

  • • 写时复制(COW)
  • • 页脏标记传播
  • • 回写粒度控制
  • • 页缓存失效同步

于是内核干脆禁止写入。

只允许带有 VM_DENYWRITE 标志的 VMA 参与合并。

而这个标志通常只会在 execve() 加载可执行文本段时设置。

也就是说——这个特性几乎只服务于可执行代码页。


三、它为何最终失败?

3.1 设计本身就是“外挂式”方案

页缓存本身并不知道自己正在被合并成大页。

这就像绕过数据库引擎,在存储层偷偷拼接数据块。

短期有效,长期难维护。


3.2 遇到写入时只能粗暴回退

如果某进程打开文件进行写操作:

File opened for write      ↓Invalidate all cached THPs      ↓Drop back to base pages

整个文件页缓存直接清空,再重新建立基础页缓存。

这不是优雅降级,而是“推倒重来”。


3.3 可写支持始终没来

配置项至今仍叫:

CONFIG_READ_ONLY_THP_FOR_FS

而且依旧带着 experimental 标签。

承诺的写支持,始终没有落地。


四、真正改变规则的人:Folio 机制

2020 年底,Matthew Wilcox 引入 Folio(页簇) 概念。

最初只是优化复合页处理,但很快演变成内核统一的大页管理抽象。


4.1 Folio 是什么?

Folio 是一个逻辑内存单元,可表示:

  • • 单个基础页
  • • 多页组合
  • • 超大页

它不再局限于传统 Page 结构。


4.2 核心思想:按需扩大管理粒度

过去:

Page Cache = 4KB page only

现在:

Page Cache = variable-sized folio

4.3 架构演进图

旧模式(2019):Page Cache (4KB aware only)        ↑   偷偷合并        ↑  khugepaged + THP新模式(2025+):Filesystem    ↓Folio-aware Page Cache    ↓Native Large Folio / mTHP

五、为什么 Folio 更优雅?

5.1 原生支持大块数据传输

例如块设备 I/O:

/* mm/filemap.c */folio = filemap_get_folio(mapping, index);

直接处理多页单位。


5.2 支持多尺寸 THP(mTHP)

传统 THP 固定 2MB。

现在支持:

  • • 8 页块
  • • 16 页块
  • • 更灵活的粒度组合

这叫 mTHP(multi-size THP,多尺寸透明大页)。


5.3 降低内部碎片

不是所有场景都适合 2MB。

Folio 能按需扩展,避免浪费。


六、删除旧功能:不是倒退,而是逼生态前进

2026 年,Zi Yan 提议移除旧实现。

改为:

  • • 删除 CONFIG_READ_ONLY_THP_FOR_FS
  • • 仅在支持大 Folio 的文件系统上启用只读 THP

6.1 当前支持情况

支持大 Folio 的文件系统并不多:

  • • XFS
  • • ext4(部分配置)

其他文件系统可能出现性能回退。


6.2 内核社区的态度

Matthew Wilcox 的观点很直接:

如果保留 fallback,文件系统就永远不会进步。

这是一种典型的内核推动策略——通过移除兼容层迫使生态升级。


七、应用场景影响分析


受益场景

  • • 大型数据库缓存
  • • 高吞吐文件服务器
  • • 容器镜像分发
  • • 高并发共享库加载

风险场景

  • • 依赖旧文件系统的发行版
  • • 未支持 Folio 的存储栈
  • • 混合读写工作负载


总结:Linux MM 的底层哲学正在改变

这次删除的,不只是一个实验性功能。

它象征着 Linux 内核内存管理的一次范式切换:


从“补丁式增强”到“原生抽象重构”

旧方案:

  • • 在页缓存之外拼接 THP
  • • 靠后台线程偷偷优化

新方案:

  • • 从数据结构层原生支持大页
  • • 让页缓存天然理解多尺寸内存块

深层洞察:真正高质量的优化不是加功能,而是改抽象

只读文件 THP 曾经是聪明的工程折中。

但随着 Folio 成熟,它变成了技术债。

Linux 最终选择删除它,不是因为它没价值,而是因为更好的体系已经出现。


这也是内核开发最值得学习的一点:

当底层抽象升级后,旧优化路径必须被淘汰,否则只会阻碍架构演进。

很多系统性能问题,最终都不是算法问题,而是抽象层次的问题。

Linux 这次做的,不是修补,而是换底座。

这才是真正的长期主义。


感谢阅读!欢迎反馈与评论。

最新文章

随机文章