为什么每个程序都"以为"自己独占内存?

你的电脑同时跑着几十个程序,每个程序都觉得自己拥有整个 4GB/16GB 地址空间,互不干扰。一个程序崩了,其他程序照常运行。这靠的是虚拟内存——现代计算机最被低估的功臣之一。今天讲透它解决了哪三件"没有它就真不行"的事。

一、没有虚拟内存的世界:灾难现场

设想一台没有 MMU 的机器,程序发出的地址直接就是物理地址:

  • 互相踩踏:两个程序同时往地址 0x1000 写,谁后写谁覆盖,前一个的数据说没就没
  • 内存不够就真没辙:需要 4GB 工作集的程序,跑在 2GB 内存的机器上直接失败——哪怕它同时只用一小块
  • 碎片:物理内存被切得七零八落,凑不出一块连续大空间,大块申请失败

这三件事——隔离、容量、碎片——没有虚拟内存时都是硬伤。

二、虚拟内存的三件大事

1. 隔离:程序崩了不该带走全部

每个进程有独立的虚拟地址空间,由内核通过各自的页表维护。进程 A 的虚拟页只能翻到分给 A 的物理页,翻不到 B 的——A 越界写,MMU 翻译时发现"没权限/没映射",直接拒绝并触发异常,最多杀掉 A。

**这堵"硬件强制的墙"**靠 MMU 的权限位,不是程序自觉——所以你能开十个浏览器标签页,一个渲染进程崩了,别的照常跑。

2. 容量:让内存"看起来比实际大"

程序启动时,内核不把全部数据搬进物理内存,只建立映射、标记"还没装进来";程序真正访问到某一页才触发缺页,从磁盘临时调入——这就是按需分页

于是:一个声明 10GB 数组的程序,只要实际只访问几百 MB,物理内存就只消耗几百 MB。程序"以为"自己有 10GB,物理上按需给付。系统还允许所有程序申请的虚拟内存之和超过物理总量(过度承诺),大幅提升利用率。

3. 共享与写时复制:省内存的利器

  • 共享:多个进程加载同一个动态库,物理上只需一份代码段,各自映射到不同虚拟地址
  • 写时复制(COW):fork 子进程时不复制父进程内存,父子共享物理页并标记只读,谁先写才复制谁的那页——fork 一个 2GB 进程瞬间开销只有几 KB 页表,这就是 Linux fork 快得离谱的原因

三、代码演示:按需分页的威力

# 程序声明 10 页,物理内存只有 4 页,只访问其中部分页
phys_pages = 4
accessed = [0, 1, 5, 8]   # 程序实际访问的页
page_faults = 0
resident = []
for page in accessed:
    if page not in resident:
        page_faults += 1
        resident.append(page)   # 缺页 -> 从磁盘调入
print(f"程序声明 10 页, 物理内存 4 页, 实际访问页 {accessed}")
print(f"缺页次数: {page_faults}(每次缺页才从磁盘调入)")
print(f"物理占用: {len(resident)} 页")
print(f"结论: 10GB 的程序只占几页物理内存就能运行")

运行输出:

程序声明 10 页, 物理内存 4 页, 实际访问页 [0, 1, 5, 8]
缺页次数: 4(每次缺页才从磁盘调入)
物理占用: 4 页
结论: 10GB 的程序只占几页物理内存就能运行

声明 10 页、物理只有 4 页,程序照样跑——每次访问到没驻留的页才触发一次缺页调入。这就是"大程序跑在小内存机器上"的秘密。

四、避坑清单

  1. 过度承诺有代价:所有程序同时用满虚拟内存会触发 OOM killer 杀进程——别把虚拟内存当物理内存
  2. 缺页不是免费的:频繁缺页(thrashing)会让系统卡死,工作集必须装得下物理内存
  3. 页表本身也占内存:多级页表是为省内存而设计,4 级页表翻译一次要多次访存(靠 TLB 加速)
  4. MCU 没有虚拟内存:裸机/RTOS 程序直接跑物理地址,隔离靠自觉——这是嵌入式与通用计算的本质区别
  5. 看内存别只看任务管理器:虚拟内存占用高不代表物理吃紧,看"工作集"

五、想系统学操作系统?

本文精选自 ima 知识号【Kruptos】《操作系统内核与驱动详解》订阅库(第 027 期为什么需要虚拟内存、第 028 期分页、第 029 期页表地址翻译等 100 期系统教程,从进程线程、虚拟内存、调度算法到文件系统与驱动开发,每期配可运行代码)。

📚 完整系列 100 期 + 配套代码,已在 ima 知识号发布

本文只是系列的一个切片。完整系列(100 期系统教程 + 每期可运行代码)在 ima 知识号【Kruptos】持续更新中:

  • 🗂 67+ 技术知识库:信号与系统、SDR 软件无线电、数字信号处理、操作系统、AI Agent、大模型微调……几乎覆盖全部软硬件技术栈
  • 🧠 8 款 AI 技能:系列生产、知识库管理、CMMI 受管开发、自进化 Agent 等,已在 ima 技能广场上架,即装即用
  • ✅ 全部免费订阅,后续更新自动推送

🔍 订阅方式:打开 ima(腾讯智能工作台)→ 搜索「Kruptos」→ 一键订阅。或在 ima 内直接搜索《操作系统内核与驱动详解》等知识库名称。

💬 你遇到过 OOM 或内存"越用越多"的诡异问题吗?评论区聊聊——想看页表细节还是 COW 原理,点赞高的安排。


作者:Kruptos(西电毕业,13 年无线通信/DSP/嵌入式科研)|原创内容,转载注明出处

Logo

openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构

更多推荐