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

【操作系统百科】虚拟内存模型

文章导航

分类入口
os
标签入口
#vm#mmap#overcommit#cow#address-space

目录

子系列 D 开篇。虚拟内存(VM)是一套给进程假象的机制:每个进程以为自己独占整块大地址空间,实际由硬件 MMU + 内核页表管理把 VA 映射到 PA,或根本没映射。这套抽象支撑了隔离、保护、swap、mmap、COW、共享库。本文讲它的整体模型。

一、先看全景

flowchart LR
    CODE[进程代码<br/>访问 VA] --> MMU[MMU/TLB]
    MMU -->|命中| PA[物理地址]
    MMU -->|miss| WALK[page walk<br/>读页表]
    WALK --> PT[多级页表 CR3/TTBR]
    PT -->|present| PA
    PT -->|!present| PF[缺页 #PF]
    PF --> KMM[内核 mm<br/>handle_mm_fault]
    KMM -->|anon/file/swap/cow| FILLPT[填 PTE]
    FILLPT --> MMU
    classDef sw fill:#388bfd22,stroke:#388bfd,color:#adbac7;
    classDef hw fill:#3fb95022,stroke:#3fb950,color:#adbac7;
    classDef err fill:#f0883e22,stroke:#f0883e,color:#adbac7;
    class CODE,KMM,FILLPT sw
    class MMU,PT,PA hw
    class PF err

二、VM 给了什么

  1. 进程隔离:A 进程看不见 B 进程的内存
  2. 保护:内核空间、只读段、NX 段受 MMU 强制
  3. 大地址空间:64 位下有 128TB+ 用户空间,远大于物理 RAM
  4. mmap 语义:文件映射、匿名映射、共享/私有
  5. COW:fork 不复制物理页,写时再分离
  6. Demand paging:不访问的地址根本不分物理页
  7. Swap:物理压力大时把冷页换到磁盘

三、代价

四、地址空间布局(x86_64 Linux)

0x0000_0000_0000_0000  ┌─────────────────┐
                       │ NULL guard      │
                       ├─────────────────┤
                       │ text (.text)    │ 可执行代码
                       ├─────────────────┤
                       │ data/bss        │ 全局/静态
                       ├─────────────────┤
                       │ heap (brk)      │ 向上生长
                       │       ↓         │
                       │                 │
                       │ mmap 区         │ 向下生长(glibc)
                       │       ↑         │
                       │                 │
                       ├─────────────────┤
                       │ stack           │ 向下生长
0x0000_7fff_ffff_ffff  ├─────────────────┤
                       │ 非规范空洞       │ 47 位有效
0xffff_8000_0000_0000  ├─────────────────┤
                       │ 内核空间        │
0xffff_ffff_ffff_ffff  └─────────────────┘

5 级分页(LA57)扩展到 57 位,上限到 128PB,但默认不开启。

查看实际布局:cat /proc/$$/maps

五、mmap 的四个象限

                         shared (MAP_SHARED)    private (MAP_PRIVATE)
file-backed (fd)    ┌──────────────────────┬──────────────────────┐
                    │ 对文件可见的共享内存 │ COW 私有映射(如 .so)│
                    │ 如 DB data file       │ 读共享,写分家        │
                    ├──────────────────────┼──────────────────────┤
anonymous           │ POSIX shm /           │ 普通 malloc 大块      │
 (MAP_ANONYMOUS)    │ 父子 fork 后仍共享    │ 堆扩展               │
                    └──────────────────────┴──────────────────────┘

关键 flag:MAP_POPULATE(提前分配)、MAP_LOCKED(mlock)、MAP_HUGETLBMAP_FIXED_NOREPLACE

六、page 的状态机

一个物理页可能处于:

/proc/meminfo 给宏观分类;page_ownerpage-types 给细粒度。

七、overcommit

Linux 允许”超额承诺”:malloc 拿到 VA 不立刻分物理页。策略:

vm.overcommit_memory
  = 0   启发式(默认):大分配拒绝,小的允许
  = 1   从不拒绝(所有 malloc 都成功)
  = 2   严格:按 CommitLimit = swap + RAM*ratio
vm.overcommit_ratio    默认 50

争议:

八、COW:fork 的灵魂

fork() 复制 mm_struct + VMA,但不复制物理页——所有页标只读,任一方写触发 #PF → 分一份私有页,把写的这页 COW 出来。

parent: [VA=0x1000] -----> PA=X (RO)
child:  [VA=0x1000] -----> PA=X (RO)
// child 写 → #PF → 分配 PA=Y,copy X→Y,child PTE 改成 PA=Y (RW)

fork+exec 热路径里 99% 的页根本不会被写(马上 exec 就释放了),COW 把 fork 从”O(工作集大小)“降到”O(VMA 个数)“。

九、保护与特权

PTE 里的控制位:

内核靠这些 bit 实现:

十、mmap 工程要点

十一、观察与诊断

cat /proc/$$/maps              # VMA 列表
cat /proc/$$/smaps             # 每 VMA 的 RSS/PSS/Swap/...
cat /proc/$$/status | grep Vm  # VmPeak/VmRSS/VmSwap
pmap -x $$                     # 友好版
vmtouch /path/file             # 看文件缓存状态

观察 overcommit:

grep -E "Commit(Limit|Allocated|ed_AS)" /proc/meminfo

十二、小结


参考文献

工具


上一篇cpufreq governors:频率调节 下一篇x86_64 多级页表

同主题继续阅读

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

2026-04-25 · os

【操作系统百科】缺页处理

缺页(page fault)是 VM 的核心事件——PTE 不 present 就触发 #PF。本文讲 major/minor/COW/swap/userfault 五种缺页控制流、do_page_fault 调用链、hugefault、userfaultfd 在 CRIU/Live Migration 的角色。

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 不靠磁盘。

2026-05-03 · os

【操作系统百科】Slab/SLUB 分配器

buddy 只管页粒度(4K+),内核大多数对象只有几十到几百字节。slab/SLUB 在 buddy 之上做对象级缓存。本文讲 slab 历史、SLUB 接手、SLOB 退场、kmem_cache、per-CPU cache、KASAN 集成。


By .