虚拟内存
虚拟内存通过地址转换,把虚拟页映射到物理页框。本文负责页表、TLB、缺页、映射与回收。
1. 面试核心
先记住这几条,再读正文- 地址映射。 页表保存虚拟页到物理页框的映射及访问权限。
- TLB 与缺页。 TLB 缓存地址转换,未命中时查页表,缺页再由内核处理。卡 · 面试核心
- 写时复制。 写时复制先共享物理页,写入时再建立私有副本。卡 · 写时复制与文件映射
- 共享与私有映射。 MAP_SHARED 的修改可对其他映射可见,MAP_PRIVATE 使用写时复制。
- 地址空间与驻留内存。 虚拟地址大小与驻留内存分别表示地址范围和已驻留页面。
2. 地址转换路径
虚拟地址由虚拟页号和页内偏移组成。页表把页号映射成物理页框号,页内偏移保持不变。访问还需通过读写与执行权限检查。
TLB 命中后,可直接使用缓存的转换结果。未命中时,处理器或系统机制继续查页表。页表映射有效时,查询完成即可继续访问。
不同进程的同一虚拟地址可映射到不同物理页。共享内存则让多个映射指向同一批页。隔离由映射和权限共同实现。
2.1 多级页表与大页
多级页表按需分配下级表,适合稀疏地址空间。代价是 TLB 未命中时需要多级查找。
大页扩大单条 TLB 映射覆盖的范围,也减少页表项。代价包括更大的分配粒度和内存碎片。Linux 的具体页大小取决于架构与配置。
3. 缺页与按需分配
访问缺少映射或违反权限的页面时,会触发异常。内核根据虚拟内存区域和权限决定处理方式。
| 情况 | 处理方式 |
|---|---|
| 新匿名页首次写入 | 分配清零的物理页并建立映射。 |
| 写时复制页发生写入 | 建立可写私有页,必要时复制旧内容。 |
| 文件页尚未驻留 | 从文件读取所需内容。 |
| 页面已换出 | 从交换区读回。 |
| 非法地址或权限错误 | 向进程发送信号等异常处理。 |
minor fault 无需从存储读入页面。major fault 需要相应 I/O。TLB 未命中只缺少转换缓存,页表仍可有效。
4. 写时复制与文件映射
Linux fork 后,父子进程先共享可复制的物理页。写入时触发保护异常,再建立私有可写页。fork 因此省去立即复制全部数据的成本。写入密集时,后续缺页和内存占用会增加。
mmap 将文件或匿名区域映射进地址空间。MAP_PRIVATE 对修改使用写时复制,修改留在私有映射。MAP_SHARED 的修改可被其他共享映射观察。文件支持的共享映射还会更新底层文件。
共享映射的可见性与落盘时间是两个问题。文件映射要主动请求同步时,可使用 msync(MS_SYNC)。多个进程并发更新还需同步机制。
5. 页面回收与内存指标
文件支持的干净页可直接回收,再次访问时重新读取。脏页需要先写回。匿名页的回收还涉及交换配置或释放进程内存。
虚拟内存大小统计地址范围。RSS 统计驻留页,共享页会在多个进程中分别计数。PSS 按共享者分摊共享页,更适合比较实际占用。
工作集超过可用内存时,频繁回收和缺页会拖慢执行。反复换入换出称为抖动。应结合 major fault、I/O 和工作集观察。
6. 使用边界
申请虚拟空间只建立地址使用的条件。实际页面可在后续访问时分配。Linux 的 overcommit 策略允许部分分配先获准。内存不足仍会在后续访问或分配阶段暴露。
内存增长应结合 RSS、PSS 和映射类型判断。大虚拟地址范围本身不足以认定泄漏。
7 · 面试题卡片
本页题目与参考回答
7.1 虚拟内存有什么作用,缺页一定意味着从磁盘读取吗?
考察重点:地址空间、地址转换缓存与不同类型缺页的处理。
参考回答
虚拟内存分离进程地址与物理内存,支持隔离和按需分配。
缺页可由匿名页分配、写时复制或磁盘读取处理。只有需要存储 I/O 的缺页才涉及读盘。TLB 未命中时,页表仍可提供有效映射。
7.2 fork 的写时复制与 mmap 的共享映射有什么区别?
考察重点:私有修改、共享可见性与同步。
相关内容:写时复制与文件映射。
参考回答
写时复制让初始页面共享,写入后建立私有副本。
MAP_PRIVATE 使用这一语义,修改留在本进程映射。MAP_SHARED 允许其他共享映射观察修改。文件支持的映射还会更新底层文件。共享访问仍需同步,落盘时机还需单独控制。
7.3 多级页表和大页分别解决什么问题,有哪些代价?
考察重点:稀疏映射、TLB 覆盖范围与分配粒度。
相关内容:多级页表与大页。
参考回答
多级页表按需分配下级表,减少稀疏地址空间的表项占用。
代价是未命中 TLB 时的多级查找。大页提高每条 TLB 项覆盖的内存范围。但大页分配粒度更大,会增加碎片和分配压力。