3.1 基本概念:逻辑地址与物理地址
搞清"程序看到的地址"和"内存真实的地址"是两回事,本节就通了。
- 逻辑地址(相对地址)——程序里用的地址,从 0 开始编号,是"程序眼里的世界"。
- 物理地址(绝对地址)——内存条上真实的地址。
- 地址重定位——把逻辑地址变成物理地址的过程。程序运行时由硬件(如页式的地址变换机构)动态完成, 所以叫动态重定位。
为什么需要它
- 程序编译时不知道自己会被装到内存的哪一段;由操作系统在装载/运行时统一换算,程序才能"随便放"。
3.2 分区管理与分配算法
老式内存管理的做法,考"哪个算法找哪块"。
- 固定分区——内存提前切成若干等长/不等长区,一区一程序。简单,但容易浪费(程序小、分区大)。
- 可变分区——按需分配,用多少给多少。会产生"内存碎片"(离散的小空隙)。
空闲区分配算法的三个套路(名字—策略对照记):
| 算法 | 怎么找 | 特点 |
|---|---|---|
| 首次适应 | 从低地址开始找第一个够大的 | 简单快;低地址区容易磨碎 |
| 最佳适应 | 找最小的够用块 | 看似省,留下更多小碎片(最差策略名声) |
| 最坏适应 | 找最大的块切 | 剩下的碎块还能用;大作业来了就没了 |
课堂练习(2 题)
- "找最小可用空闲区"是哪种分配算法? 答:最佳适应算法。
- 可变分区会产生什么问题?固定分区呢? 答:可变分区产生外碎片(分散的空闲小空隙);固定分区产生内碎片(分区内的浪费)。
3.3 页式管理:地址变换(计算题)★
"逻辑地址 = 页号 + 页内偏移"——软考最爱要求"算出物理地址"。
分页思想:把逻辑空间等分成页(大小固定,如 4KB),物理内存等分成同样大小的页框(块)。 程序的一页可以装到任意一个空闲页框里——内存利用率高,也没有外部碎片。
逻辑地址的结构: [ 页号 P | 页内偏移 W ] 页表:每个进程一张,记录 "页号 → 页框号" 的对应关系 变换过程:逻辑地址 → 拆出页号P与偏移W → 查页表得页框号M → 物理地址 = M × 页大小 + W
例题:手把手算一次
页面大小 4KB(4096 字节);逻辑地址 13000;该页在页表中的页框号为 8。求物理地址。
第 1 步:求页号与页内偏移 页号 = 13000 ÷ 4096 = 3(整除部分) 偏移 = 13000 − 3×4096 = 13000 − 12288 = 712 第 2 步:查页表,页号 3 对应的页框号 = 8(题给) 第 3 步:拼物理地址 物理地址 = 8 × 4096 + 712 = 32768 + 712 = 33480
配套常识
- 页大小是 2 的整数次幂时:页号=地址高位、偏移=地址低位(4KB → 低 12 位是偏移)。
- 页表在内存里,由操作系统为每个进程维护;增加快表(TLB)可加速查表。
- 分页解决的是"内存碎片和分配"问题;页是物理单位,对用户不可见。
课堂练习(3 题)
- 页面大小 1KB,逻辑地址 2500,页号和偏移分别是多少? 答:页号 = 2500 ÷ 1024 = 2;偏移 = 2500 − 2048 = 452。
- 上题若页号 2 对应的页框号是 5,物理地址是多少? 答:5 × 1024 + 452 = 5572。
- 页表的作用是什么? 答:记录逻辑页号到物理页框号的映射,供地址变换使用。
3.4 段式与段页式:分页 vs 分段
一张对比表搞定,考试就问"谁是逻辑单位、谁是物理单位"。
| 分页 | 分段 | |
|---|---|---|
| 划分依据 | 物理单位,等长切分 | 逻辑单位,按程序模块(代码段/数据段)划分,长度不等 |
| 对用户 | 不可见(系统自动) | 可见(编写者划分) |
| 地址结构 | 页号 + 页内偏移 | 段号 + 段内偏移 |
| 主要目的 | 提高内存利用率、消除外碎片 | 便于模块化、共享与保护 |
段页式 = 先分段(逻辑模块)再分页(物理存储):一个程序分成若干段,每段再分页。 地址变换要查两次表(段表 → 页表),最灵活但也最复杂。
课堂练习(2 题)
- 段的长度是固定的还是可变的?页呢? 答:段长可变(按逻辑模块定);页长固定(系统规定,如 4KB)。
- 段页式地址变换需要查几张表? 答:两张——先查段表找到该段的页表,再查页表找到页框。
3.5 虚拟内存与页面置换(计算题)★
"内存不够用怎么办"——虚拟内存 + 置换算法。会数缺页次数就是分。
虚拟内存的思想:程序不必全部装入内存就能运行;只把常用部分放内存,其余留在磁盘。 访问的页不在内存时发生缺页中断,操作系统把缺的页从磁盘调入—— 如果内存满,还要先按置换算法淘汰一页。
三种置换算法
- OPT(最优)——淘汰"未来最久不用"的页。理论最优,无法实现,作为标尺。
- FIFO(先进先出)——淘汰最早进入的页。实现简单;可能发生 Belady 异常(帧变多反而缺页更多)。
- LRU(最近最久未用)——淘汰过去最久没被访问的页。性能接近 OPT,硬件开销较大。
例题:数缺页次数(3 个页框)
页面访问序列:2, 3, 2, 1, 5, 2, 4, 5, 3, 2, 5, 2
FIFO 走一遍(淘汰"最早进入"的页): 2 → [2] 缺 3 → [2,3] 缺 2 → 命中 1 → [2,3,1] 缺 5 → 淘汰2 → [3,1,5] 缺 2 → 淘汰3 → [1,5,2] 缺 4 → 淘汰1 → [5,2,4] 缺 5 → 命中 3 → 淘汰5 → [2,4,3] 缺 2 → 命中 5 → 淘汰2 → [4,3,5] 缺 2 → 淘汰4 → [3,5,2] 缺 → FIFO 共缺页 9 次(12 次访问,命中 3 次) 三种算法对比(同一序列、3 个页框): OPT 6 次 < LRU 7 次 < FIFO 9 次 结论:OPT 最优但不可实现;LRU 效果好;FIFO 最简单但最差。
几个配套概念
- 缺页中断属于内部中断(软中断),不属于 I/O 中断。
- 抖动(颠簸)——页面频繁换进换出,CPU 大部分时间在等页,效率骤降。
- 局部性原理——程序一段时间内倾向于集中访问某些页,这是虚拟内存能快的基础。
课堂练习(2 题)
- 哪种置换算法可能发生 Belady 异常? 答:FIFO(增加物理块数反而可能增加缺页次数)。
- 缺页中断发生时操作系统要做什么? 答:把所需页面从磁盘调入内存;内存满时先按置换算法淘汰一页;调整页表后重新执行被中断的指令。