在现代操作系统中,内存管理是决定系统性能与扩展性的核心基石。随着云计算、大数据以及高性能计算(HPC)的爆发,Linux 系统常常需要应对数以千计的进程同时运行并共享超大内存内存的场景。然而,传统的 Linux 内存管理架构在这种极端场景下正遭遇一项隐形的“内存小偷”——页表冗余。

为了解决这一痛点,Linux 内核社区正在积极推进一项名为 mshare 的前沿技术。本文将从 Linux 内存管理的基础概念出发,带您深入了解 mshare 诞生的背景、运作原理以及最新的技术进展。

一、 核心基础概念:页表与 TLB

在探讨 mshare 之前,需要先理解 Linux 是如何管理虚拟内存与物理内存的。

1. 页表 (Page Table) —— 内存映射的“字典”

在 Linux 中,CPU 和操作系统使用的是虚拟内存,而真实的物理硬件使用的是物理内存。为了简化管理,系统将虚拟内存和物理内存都划分为固定大小的块(通常每块大小为 4KB):

  • 页 (Page): 虚拟内存的分块。

  • 页帧 (Page Frame): 物理内存的分块。

页表就是操作系统维护的一张映射表(字典),它记录了虚拟页(Page)对应哪一个物理页帧(Page Frame)。

每一个进程都以为自己独占了整个系统的内存空间(拥有自己独立的虚拟地址空间)。当进程访问某个虚拟地址时,CPU 的内存管理单元(MMU)就会去查这个进程的页表,找到对应的物理内存。由于 64 位系统的地址空间巨大,Linux 采用了多级页表(通常是 4 级或 5 级)结构,像树状目录一样按需加载,以节省页表自身的内存占用。

2. TLB (Translation Lookaside Buffer) —— 页表缓冲“快表”

虽然多级页表节省了空间,但它带来了一个致命缺陷:。CPU 每次读写一个内存数据,都要先层层查找 4~5 级页表(这意味着访问 4~5 次物理内存),最后才能访问到真正的数据。

为了解决这个瓶颈,硬件引入了 TLB。TLB 是一种集成在 CPU 芯片内部的高速缓存(Cache),专门用来存放最近使用过的“虚拟地址到物理地址的映射条目”。

当 CPU 需要转换地址时,会首先查询 TLB:

  • TLB 命中(Hit): 直接获取物理地址,只需 1 个 CPU 周期。

  • TLB 未命中(Miss): 传统地去查内存中的多级页表,并将结果新写入 TLB。

由于每个进程的页表都不同,当 CPU 从进程 A 切换到进程 B 时,TLB 里缓存的 A 的映射就会失效。Linux 需要刷新(Flush)TLB,或者使用进程上下文标识符(ASID)来区分不同进程的缓存。

二、 传统共享内存的痛点

Linux 可以在进程之间共享内存(例如通过 shmgetmmap),但(几乎总是)每个进程都拥有自己的一套页表。

在大量进程共享同一个内存区域的情况下,问题就显现出来了:所有进程的页表叠加起来的总大小,甚至可能会超过共享内存本身的大小。 > 举个例子: 假设系统有一个 1TB 的共享内存区域。如果成百上千个不相关的进程共同访问这块内存,每个进程都要在自己的进程空间里为这 1TB 的数据建立一套复杂的 4 级或 5 级页表。当有 1000 个进程时,光是页表本身就要吃掉数个 TB 的系统内存,造成极大的资源浪费。

因此,让不相关的进程能够共享指向同一块共享内存的页表,这一想法长期以来备受内核社区关注。

三、 mshare 技术:原理与最新进展

Anthony Yznaga 是最新一位试图推动该想法(被称为 “mshare”)落地的开发者;在 2026 年 Linux 存储、文件系统、内存管理和 BPF 峰会(LSFMM+BPF)的内存管理分论坛上,他介绍了这项工作的最新进展。

这已经不是页表共享第一次(甚至第二次)进入 LSFMM+BPF 的议程了;该议题最近一次讨论是在 2024 年,当时 Khalid Aziz 向小组更新了该提案的进展。此后 Aziz 已经退休,Yznaga 接手了这项工作。

1. 整体架构与运作原理

该补丁集的整体架构并没有改变:

  • 创建共享区域: 共享始于某个进程通过在特殊的 msharefs 文件系统中创建一个文件来建立共享内存区域。

  • 独立管理结构: 该区域在创建时会自带一个独立的 mm_struct 结构,专门用于管理该区域的页表。

  • 挂载与映射: 随后,每个参与共享的进程都可以通过打开并映射这个 msharefs 文件来挂载到该区域,从而在进程的地址空间中创建一个特殊的虚拟内存区域(即“窗口 VMA”,window VMA)来代表该共享区域。

  • 页表级共享: 当发生缺页异常或其他内存管理操作并遇到该窗口 VMA 时,系统会沿着指针找到那个特殊的 mm_struct,并在其公共页表上进行操作。这意味着,无论有多少个进程连接进来,这块共享内存对应的页表在系统里永远只有一份。

2. API 的演变:重回系统调用

至少在 2024 年以及 2025 年 Yznaga 提交更新版补丁集时,情况还是这样的。不过在本次会议上,他透露虽然 mshare 的底层实现基本保持不变,但其 API 已经切回了系统调用的形式,正如更早期的版本那样。此前曾有人提出使用单个 mshare() 系统调用,而现在则演变成了一整套系统调用。

现在,共享区域通过 mshare_create() 创建:

int mshare_create(unsigned int flags);

该调用将返回一个代表新区域的文件描述符;目前唯一支持的标志(flags)值是 O_CLOEXEC。随后必须通过 ftruncate() 调用来设置该区域的大小。接着,通过调用 mshare_attach() 将共享区域映射到调用进程的地址空间中:

int mshare_attach(int fd, unsigned int offset, unsigned int size,
                  void *addr, unsigned int flags);

(注:Yznaga 在幻灯片中并未展示参数的具体类型,因此此处填入了一些看起来合理的类型)。

此外,还有一个 mshare_map() 用来执行类似于 mmap() 的操作,为共享区域内的地址设置后端存储。同时还有其他各种调用,包括 mshare_advise()mshare_protect(),用于控制该区域的管理。不过,Yznaga 并未详细说明其他进程是如何找到并挂载到该区域的。

3. 所有权模型的优化

该共享区域的所有权模型发生了一些变化:调用 mshare_create() 的进程在该进程的生命周期内拥有此区域;当该进程退出或关闭文件描述符时,该区域就会消失,其他进程中的映射也会被移除。

Yznaga 表示,这一改动带来了三大核心好处:

  1. 简化了控制组(cgroup)的内存记账工作。

  2. 使区域的生命周期更加明确。

  3. 并在系统触发内存不足(OOM)时,为 OOM Killer 杀死进程提供了一个明确的目标。

四、 攻坚方向与未来展望

Yznaga 在演讲结束时总结了他目前正在解决的问题以及 mshare 面临的挑战:

  • 页表遍历(Page-table walking)的锁机制: 这是一个巨大的挑战。尤其是如何在进程自身的窗口 VMA 与 mshare 区域的 VMA 之间获得正确的锁并发控制。

  • 常驻内存集(RSS)统计: 目前使用 mshare 的进程的 RSS 统计是错误的。因为共享区域的内存信息存储在那个特殊的 mm_struct 中,并没有暴露给外部的常规统计工具。

  • 对创建者进程的依赖: 目前的设计要求创建该区域的进程必须一直存活。未来如果能引入一种“所有权转移机制”,让创建者可以把区域移交给其他进程然后退出,那将非常有价值。

潜在应用场景

内核社区也在积极寻找该特性的更多潜在应用场景:

  1. 高性能计算(HPC): Jason Gunthorpe 提到了需要共享海量资源的 HPC 进程,mshare 能够完美契合其高并发、大内存共享的诉求。

  2. Android Zygote 进程: Zygote 是 Android 系统中所有应用进程的父进程。各 App 进程之间存在大量的公共基础库和共享代码。如果能利用 mshare,将显著降低系统内存开销。但挑战在于,如果某个 App 进程对该区域进行了写操作,这些修改不应该对其他挂载的进程可见,因此在这种情况下必须支持“取消页表共享”(unshare page tables / 写时复制机制的变体)。

关于 TLB 刷新的争论

还有一位与会者询问了共享区域内 TLB 刷新的处理方式。Yznaga 回答说,系统维护了一个由所有共享该区域的进程组成的链表;当需要进行 TLB 刷新时,系统会遍历该链表并逐个刷新每个进程。Gunthorpe 指出,这个链表听起来非常像 MMU 通知器(MMU notifier);Yznaga 则回应称他曾尝试过使用通知器,但在这种情况下并不奏效。

在会议的尾声,Matthew Wilcox 提出了一项简化建议:允许每个进程将共享区域映射到不同的虚拟地址增加了该特性的复杂性;如果强制要求该区域在所有进程中必须映射到相同的地址,是否会是一个有用的简化?然而,会场内的反应明确表明这并不是一个受欢迎的想法(灵活性对于现代应用依然至关重要)。

Wilcox 最终总结道,一旦 mshare 特性最终合并,Linux 将有可能彻底移除由 hugetlbfs 子系统实现的页表共享功能——这也是目前 Linux 系统上实现此类共享的唯一方式。mshare 将作为一种更通用、更优雅的方案,引领 Linux 内存管理走向下一代演进。

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐