摘要
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 会带来复杂一致性问题:
于是内核干脆禁止写入。
只允许带有 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。
现在支持:
这叫 mTHP(multi-size THP,多尺寸透明大页)。
5.3 降低内部碎片
不是所有场景都适合 2MB。
Folio 能按需扩展,避免浪费。
六、删除旧功能:不是倒退,而是逼生态前进
2026 年,Zi Yan 提议移除旧实现。
改为:
- • 删除
CONFIG_READ_ONLY_THP_FOR_FS - • 仅在支持大 Folio 的文件系统上启用只读 THP
6.1 当前支持情况
支持大 Folio 的文件系统并不多:
其他文件系统可能出现性能回退。
6.2 内核社区的态度
Matthew Wilcox 的观点很直接:
如果保留 fallback,文件系统就永远不会进步。
这是一种典型的内核推动策略——通过移除兼容层迫使生态升级。
七、应用场景影响分析
受益场景
风险场景
总结:Linux MM 的底层哲学正在改变
这次删除的,不只是一个实验性功能。
它象征着 Linux 内核内存管理的一次范式切换:
从“补丁式增强”到“原生抽象重构”
旧方案:
新方案:
深层洞察:真正高质量的优化不是加功能,而是改抽象
只读文件 THP 曾经是聪明的工程折中。
但随着 Folio 成熟,它变成了技术债。
Linux 最终选择删除它,不是因为它没价值,而是因为更好的体系已经出现。
这也是内核开发最值得学习的一点:
当底层抽象升级后,旧优化路径必须被淘汰,否则只会阻碍架构演进。
很多系统性能问题,最终都不是算法问题,而是抽象层次的问题。
Linux 这次做的,不是修补,而是换底座。
这才是真正的长期主义。
感谢阅读!欢迎反馈与评论。