2019 年第 29 题:LRU 算法、局部置换、预分配 4 个页框,访问序列 0,1,2,7,0,5,3,5,0,2,7,6,问产生页置换的总次数。

我数出来缺页 9 次,可选项最大只有 6。我以为自己数错了,连数三遍都还是 9。

最后才反应过来:这题问的是置换次数,不是缺页次数。

前 4 次缺页是在填空白页框,根本没有"换出"这个动作,不算置换。9 − 4 = 5 → 答案 C。

这两个数字一定要分清:缺页次数 9,置换次数 5。凡是题目问"置换",就要扣掉开头那些把空页框填满的次数。


〇、先花两分钟:页面置换到底在换什么

先扫盲三个词:

  • 缺页(Page Fault):要访问的页面不在内存里,触发一次缺页中断。只要没命中,就是缺页。

  • 置换(Replacement):内存满了还得往里放新页,就必须挑一个旧的踢出去。这个"挑一个踢出去"的动作才叫置换。

  • 命中:要访问的页面就在内存里,什么都不用做。

所以三者的关系是:

缺页次数 = 置换次数 + 开头把空页框填满的次数

判断口诀:内存还没装满时的缺页 → 只是"装入",不叫置换;内存满了之后的缺页 → 必须"换出旧页",才叫置换。

什么时候需要置换? 请求分页系统里,进程只把一部分页面装进内存。访问时发现页不在内存(缺页),OS 就把它从外存调进来;如果此时分配给该进程的页框已经用完,就得先选一页换出去——选哪一页,就是页面置换算法要解决的问题。


一、四种算法,一个序列,逐个手算

下面用同一个序列把三种经典算法走一遍(Clock 单独讲)。假设系统给进程分配 3 个页框,访问序列是:

2, 3, 2, 1, 5, 2, 4, 5, 3, 2, 5, 2

① 最佳置换算法 OPT(理想算法,实现不了)

规则:淘汰未来最长时间不再被访问的页面(或者干脆以后都不用了的)。

它为什么"最佳":它是开了天眼的算法——必须预先知道后面的访问序列,实际系统做不到。它的价值是作为一个理论下限,用来评价其他算法有多差。

手算过程(内存状态按「最久未用 → 最近使用」写):

访问232152453252
内存22,3命中2,3,12,3,5命中2,5,4命中2,5,3命中命中命中
缺缺缺换 1换 3换 4

→ 缺页 6 次,置换 3 次

② 先进先出 FIFO(最容易实现,也最容易出问题)

规则:淘汰最早进入内存的那一页。就像排队,先来的先走。

访问232152453252
内存22,3命中2,3,13,1,51,5,25,2,4命中2,4,3命中4,3,53,5,2
缺缺缺换 2换 3换 1换 5换 2换 4

→ 缺页 9 次,置换 6 次

注意第 5 步访问 2:2 明明刚被访问过(第 3 步),但 FIFO 不管这个,它只看"谁先来的",照样把它换走了。这就是 FIFO 不符合程序局部性原理的地方,也是它容易产生 Belady 异常的根源。

③ 最近最久未使用 LRU(考得最多,性能最好)

规则:淘汰最近最久没被用过的那一页。它相信:最近用过的,待会儿大概率还会用(局部性原理)。

访问232152453252
内存22,3命中2,3,12,1,5命中5,2,4命中4,5,35,3,2命中命中
缺缺缺换 3换 1换 2换 4

→ 缺页 7 次,置换 4 次

三种算法摆在一起看

算法缺页次数置换次数特点
OPT63理论最优,实现不了,只作参照
LRU74性能好,需要硬件支持(寄存器/栈),开销大
FIFO96实现最简单,性能最差,可能 Belady 异常

三者的比较关系:OPT ≤ LRU ≤ FIFO(缺页次数)。记住这个不等式,选择题直接排除。

2019(29) 那道题(4 个页框、LRU、序列 0,1,2,7,0,5,3,5,0,2,7,6)完整推演:

访问 0(缺) 1(缺) 2(缺) 7(缺) → 内存满:0,1,2,7   ← 前 4 次只是装入,不算置换
访问 0 命中 → 1,2,7,0
访问 5 缺 → 淘汰 1 → 2,7,0,5     ← 置换 1
访问 3 缺 → 淘汰 2 → 7,0,5,3     ← 置换 2
访问 5 命中 → 7,0,3,5
访问 0 命中 → 7,3,5,0
访问 2 缺 → 淘汰 7 → 3,5,0,2     ← 置换 3
访问 7 缺 → 淘汰 3 → 5,0,2,7     ← 置换 4
访问 6 缺 → 淘汰 5 → 0,2,7,6     ← 置换 5

缺页 9 次,置换 5 次 → 答案 C


二、LRU 的秒杀技巧:从后往前数

2015(27) 是道"看起来要画半天表,其实十秒能出答案"的题:

4 个页框,已访问序列 2,0,2,9,3,4,2,8,2,4,8,4,5,若下一页访问 7,依据 LRU 应淘汰哪一页?

不要从头模拟。 直接从序列末尾往前数,数出 k 个(k = 页框数)不同的页号:

序列尾部:... 2, 4, 8, 4, 5
从后往前:5(第1个) → 4(第2个) → 8(第3个) → 2(第4个)  ← 数够 4 个,停

数出的这 4 个就是此刻内存里的 4 个页,而其中最早数到的那个(2)就是最久没被碰过的 → 淘汰 页 2,答案 A。

原理:不管过去发生了什么,此刻内存里一定装着"最近出现过的 k 个不同页"。所以从后往前数 k 个不同页号,直接就还原了内存快照。

2025(26) 也可以用这个思路验证:3 个页框、初始已装入 0,1,2,序列 0,1,2,0,5,1,4,3,0,2,3,2,0,逐步模拟下来缺页 6 次 → 答案 B。


三、Belady 异常:页框越多,缺页反而越多

Belady 异常:分配给进程的页框数增加,缺页次数不降反升。这是反直觉的,但确实会发生。

2014(30) 直接考它:可能出现 Belady 异常的是?

  • Ⅰ. LRU → ❌(LRU 是栈式算法,不会发生)

  • Ⅱ. FIFO → ✅

  • Ⅲ. OPT → ❌

→ 答案 A:仅 Ⅱ

看一个真实算例

用经典序列 1,2,3,4,1,2,5,1,2,3,4,5:

页框数FIFO 缺页次数
3 个9 次
4 个10 次 ← 页框变多,缺页反而多了一次

原因就是前面说的:FIFO 只看"谁先来",完全不管页面最近有没有被用过,于是可能把"马上又要访问"的页换出去,而多出来的那个页框反而改变了淘汰顺序,把情况搞得更糟。

一句话记忆:只有 FIFO 会 Belady。LRU 和 OPT 都是"栈式算法"——页框越多,内存里装的页只会越多,缺页次数必然单调不增。


四、改进型 Clock:用两个位把页分成四类

Clock(时钟)算法:给每页一个访问位 A,页面排成一个环形队列。淘汰时像时钟指针一样扫,遇到 A=0 的就淘汰;遇到 A=1 就把它置 0 再跳过(给它第二次机会)。

改进型 Clock 再加一个修改位 M,一共四类(A = 访问位,M = 修改位):

2016(26) 就考淘汰次序:

类别含义淘汰优先级
(0, 0)最近没访问过,也没修改过第 1 优先淘汰(最省事,直接扔)
(0, 1)最近没访问过,但改过第 2(要写回磁盘,代价大一点)
(1, 0)最近访问过,没改过第 3(刚用过,可能还要用)
(1, 1)最近访问过,也改过最后才考虑(又要用、又要写回)

→ 淘汰次序 (0,0) → (0,1) → (1,0) → (1,1),答案 A

记忆法:先看 A(没访问过的先走),A 相同再看 M(没改过的先走,省一次写回)。

2021(28) 把改进型 Clock 和地址变换揉在一起考:虚拟地址 02A01H、页大小 4KB、2 个固定页框。

解题分三步:

① 页大小 4KB = 2^12 B → 低 12 位是页内偏移
   02A01H = 0000 0010 1010 0000 0001
   低 12 位 = A01H(页内偏移,变换前后不变)
   页号 = 02H
​
② 查页表发现 2 号页「存在位 = 0」,不在内存 → 缺页,需要置换
   按改进型 Clock 从已在内存的两页里挑一页淘汰(挑中 3 号页,它占着 60H 页框)
​
③ 2 号页装进 60H 页框
   物理地址 = 60H 拼上偏移 A01H = 60A01H

→ 答案 C:60A01H

这题的关键是页内偏移不变:页框号从 60H 来,偏移 A01H 原样搬过去,拼起来就行。


五、工作集与抖动:内存"不够用"的两种表现

工作集(2016(29))

工作集:在时刻 t,进程最近 k 次内存访问所访问过的页面集合(k 叫窗口大小),记作 w(k, t)。

2016(29):窗口大小 6,序列 …, 1,3,4,5,6,0,3,2,3,2,0,4,0,3,2,9,2,1, …,t 时刻工作集?

取 t 时刻之前最近 6 次访问:6, 0, 3, 2, 3, 2,去重 → {6, 0, 3, 2} → 答案 A

(注意 B 选项 {2,3,0,4} 是再往前 6 次的结果,不是"最近"的。)

抖动 / 颠簸(Thrashing)

抖动:刚换出去的页面马上又要访问,于是又换别的页出去,而那个页又很快被访问……系统大部分时间都花在换页上,CPU 利用率暴跌。

根因:分配给进程的页框数少于它当前的工作集大小。

2011(29) 问有效对策:

  • Ⅰ. 撤销部分进程 → ✅(减少并发进程数,把页框还给留下来的进程)

  • Ⅱ. 增加磁盘交换区容量 → ❌(抖动的主因不是外存不够)

  • Ⅲ. 提高用户进程优先级 → ❌(换页频率不会因为优先级而降低)

→ 答案 A:仅 Ⅰ

2022(30) 反过来问"不会影响缺页率的是":

  • A. 页面置换算法 → 会(LRU 通常低于 FIFO)

  • B. 工作集大小 → 会(工作集越大,给的页框不够就越容易缺页)

  • C. 进程数量 → 会(进程越多,每进程分到的页框越少)

  • D. 页缓冲队列长度 → 不会(它影响的是置换的速度,不是缺页的次数)

→ 答案 D

2020(28) 考有效访存时间由什么决定 → 四个全要:缺页率、磁盘读写时间、内存访问时间、执行缺页处理程序的 CPU 时间 → 答案 D。


六、易错点清单

  1. 把缺页次数当置换次数 → 问"置换"要扣掉开头填满空页框的次数(2019(29):9 缺页 = 5 置换)

  2. 从头模拟 LRU → 用"从后往前数 k 个不同页号"秒出内存快照(2015(27))

  3. 认为所有算法都会 Belady → 只有 FIFO(2014(30))

  4. 改进型 Clock 先比 M 再比 A → 反了,先看 A 再看 M(2016(26))

  5. 抖动时想到扩交换区 / 提优先级 → 都无效,撤销部分进程才是正解(2011(29))

  6. 工作集取"往前"而不是"最近" → 必须从 t 时刻往回取 k 次(2016(29))

  7. 认为 LRU 一定最优 → LRU 只是接近 OPT,理论上 OPT 才是下限

  8. 页缓冲队列影响缺页率 → 不影响,只影响置换速度(2022(30))

  9. 忘记页内偏移不变 → 地址变换只换页号部分,偏移原样拼接(2021(28))

  10. 以为页置换是系统调用 → 不是,它完全由 OS 内部完成(2021(32) 答案 C 是"创建新进程")


速查表(文末收藏版)

三种算法对比

算法规则缺页Belady备注
OPT淘汰未来最久不用的最少不会理论下限,实现不了
LRU淘汰最近最久未用的次少不会需硬件支持,开销大
FIFO淘汰最早进来的最多会实现最简单
Clock环形扫描访问位接近 LRU—开销小,实际系统常用

LRU 秒杀法

从序列末尾往前数,数出 k 个(k = 页框数)不同的页号
= 此刻内存快照;其中最早数到的那个 = 要淘汰的页

改进型 Clock 四类淘汰次序

(0,0) → (0,1) → (1,0) → (1,1)        先看访问位 A,再看修改位 M

关键数字关系

缺页次数 = 置换次数 + 开头填满空页框的次数
OPT ≤ LRU ≤ FIFO(缺页次数)
只有 FIFO 会出现 Belady 异常

抖动与工作集

抖动成因:分配的页框数 < 当前工作集大小
抖动对策:撤销部分进程(扩交换区、提优先级都无效)
工作集:t 时刻往前取 k 次访问,去重后的页面集合
不影响缺页率:页缓冲队列长度

本文依据:王道《操作系统考研复习指导》虚拟内存管理章节;真题题干、选项与答案均逐条核对 zhenti_all.json(2009–2025 共 799 题,操作系统部分 170 题),涉及 2011(29)、2014(30)、2015(27)(30)、2016(26)(29)、2019(29)、2020(28)、2021(28)(32)、2022(29)(30)、2025(26)(27)。文中三种算法的对比演算(序列 2,3,2,1,5,2,4,5,3,2,5,2)与 Belady 算例(序列 1,2,3,4,1,2,5,1,2,3,4,5)均为本文自行推演,与算法定义一致。

Logo

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

更多推荐