内存管理
内存管理的核心是虚拟内存:给每个进程一个独立的地址空间,物理内存由内核统一分配。面试主线:为什么虚拟、怎么转换、缺页怎么办。
虚拟内存
虚拟内存: 每进程独立地址空间, 映射到物理内存
虚拟内存解决三个问题:
| 问题 | 解法 |
|---|---|
| 隔离 | 每进程独立地址空间,互不可见 |
| 连续性问题 | 虚拟连续,物理可离散(分页) |
| 内存不足 | 按需加载 + 换出(见页面置换篇) |
进程看到的地址是虚拟的:代码里的指针是虚拟地址,访问时经页表转成物理地址。
分页与地址转换
- 页(page):虚拟内存固定大小单元(Linux 4KB),页框(frame):物理内存同大小单元
- 页表:虚拟页号 → 物理页框号的映射表
- 转换流程:虚拟地址 = 页号 + 偏移 → 查页表拿页框号 → 物理地址 = 页框号 + 偏移
TLB(快表):页表在内存里,每次访问都要查表太慢。TLB 是页表项的缓存(CPU 硬件),命中免查内存。上下文切换要刷 TLB(这就是进程切换比线程切换贵的另一个原因)。
缺页中断
访问的页不在内存(页表项无效)→ 缺页中断:
- 检查地址合法性和权限(非法 → 段错误)
- 找空闲页框;没有就换出某页(见页面置换篇)
- 从磁盘读页进内存,更新页表
- 重新执行触发缺页的指令
页错误(page fault)是常态:程序启动、mmap 文件、堆增长都触发。性能优化方向是减少缺页(局部性好)。
分段与段页式
- 分段:按逻辑(代码/数据/栈)分,段大小可变,有保护和共享语义
- 分页:固定大小,无逻辑语义,管理简单
- 现代系统:段页式(分段提供保护视图,分页负责映射)或纯分页(Linux 用分页 + 权限位)
面试追问
- 虚拟内存解决什么? 隔离、连续映射、容量扩展(换出)。进程看到的是假地址
- 页表是干什么的? 虚拟页号到物理页框的映射。TLB 缓存页表项加速
- 缺页中断流程? 查合法性 → 找页框(不够换出)→ 磁盘读入 → 更新页表 → 重执行
- 为什么进程切换比线程切换贵? 换地址空间:页表切换 + TLB 失效(后续访问全 miss)
- 分段和分页的区别? 分段按逻辑可变大小(有共享保护语义),分页固定大小(管理简单)。现代用分页加权限位