考研学习
解题方法操作系统

操作系统第 3 章:内存管理

408 操作系统「内存管理」复习:核心知识点、真题题型、通用解法与易错点。

Last updated on

本章以本站 408 真题 → 操作系统 → 第 3 章 内存管理 为主,并用 408 模拟选择题 → 操作系统 → 第 3 章 补充题型。本站也明确建议按“真题确定命题方式,再用模拟题补充”的顺序复习。第 3 章真题主要分为“基本内存管理”和“虚拟内存管理”两大部分。(Any Docs)

这一章是操作系统里计算味最重、综合性最强的章节之一。

如果第 2 章进程管理的核心是“状态 + 调度 + PV”,那么第 3 章可以压缩成一句话:

CPU 给出虚拟地址以后,到底怎样找到真正的物理内存?如果页面不在内存,又怎么办?

408 会围绕这条主线不断变形。


一、先建立整章知识地图

模块典型考法重要度
地址装入、链接、重定位概念选择题★★
连续分配首次/最佳/最坏适应、碎片、回收合并★★★
伙伴系统分裂、合并★★~★★★
基本分页页号、页内偏移、页框、物理地址★★★★★
多级页表页表大小、地址拆分、页表级数★★★★★
分段段号、段长、越界、共享★★★
请求分页缺页异常处理★★★★★
页面置换FIFO、LRU、CLOCK、改进 CLOCK★★★★★
TLB命中率、平均访存时间★★★★★
工作集与抖动工作集计算、抖动原因★★★
页面缓冲与置换、缺页率区别★★
局部性数组访问与缺页、Cache 联合★★★★
综合大题页表 + TLB + 缺页 + 置换 + 地址计算★★★★★

真正应该投入最多时间的是:

分页地址转换 → 多级页表 → TLB → 缺页 → 页面置换 → 物理地址。

这几个知识点可以单独考,也非常喜欢串成一道大题。


二、整章最重要的“地址转换模型”

以后只要看到分页题,第一反应必须是:

虚拟地址 = 虚拟页号 + 页内偏移量。

设页面大小为

那么低 位永远是页内偏移。

于是:

查页表得到页框号 后:

这就是整个分页系统计算题的母公式。

例如页大小 4KB:

那么虚拟地址 2362H:

所以:

页号 = 2,

页内偏移 = 362H。

这一步必须形成条件反射。


三、题型一:链接、装入、重定位与地址保护

1. 逻辑地址什么时候形成?

【2011 408 真题】

题意是:

虚拟内存系统中最终还要把逻辑地址转换为物理地址,那么程序的逻辑地址主要在哪个阶段形成:编辑、编译、链接还是装载?

答案:链接阶段。(Any Docs)

这一题容易把“编译”和“链接”混淆。

基本流程:

源程序

→ 编译

→ 若干目标模块

→ 链接

→ 完整逻辑地址空间

→ 装入

→ 运行期间地址转换。

可以理解成:

编译解决“每个模块自己是什么”,链接解决“大家拼在一起以后在哪里”。


2. 重定位

重定位就是:

把逻辑地址映射为物理地址。

分成两种。

类型转换时间特点
静态重定位装入时一旦装入,通常不能随便移动
动态重定位运行时借助硬件地址转换,可以移动

模拟题还考过一个重要延伸:

紧凑为什么需要动态重定位?

因为紧凑会把已经在内存中的进程移动位置。

原来:

进程A | 空洞 | 进程B | 空洞 | 进程C

移动后:

进程A | 进程B | 进程C | 大空洞

进程 B、C 的物理地址都变了。

如果程序里面直接写死物理地址,移动以后全部失效。

所以紧凑要求:

模拟题也明确以这一点设问。(Any Docs)


3. 地址保护

【2009 408 真题】

题目问:

分区分配方式下,主要采用什么措施保护各进程的内存空间?

答案:界地址保护。(Any Docs)

常见实现:

基址寄存器 + 限长寄存器。

逻辑地址 首先判断:

合法后:

其中:

:基址;

:进程地址空间长度。

一定是:

先检查,再相加。

这个思想到了分段系统完全一样。


四、题型二:内部碎片与外部碎片

这是选择题高频陷阱。

1. 内部碎片

已经分给出了,但尚未使用完。

例如一个页框 4KB,进程最后一页只有 1KB:

[1KB有效数据 | 3KB浪费]

这 3KB 已经属于该进程,因此别人无法使用。

所以是内部碎片。


2. 外部碎片

总空闲量可能足够,但被切成很多小洞。

例如:

20KB空闲 | A | 30KB空闲 | B | 40KB空闲

总共有:

但要申请 60KB 连续空间仍然失败。

因为不存在一个 60KB 的连续空洞。


必须记住的表

管理方式内部碎片外部碎片
固定分区有通常不作为主要问题
动态分区基本无有
分页有无
分段基本无有
段页式有无页框层面的外部碎片

模拟题专门把固定分区、动态分区、分页、分段、段页式混起来问,正确判断内部碎片的关键就是:

固定大小单位分配 → 容易产生内部碎片;可变连续区域 → 容易产生外部碎片。 (Any Docs)

分页绝对不要说“页面小可以减少外部碎片”。

因为:

页面变小减少的是平均内部碎片。

但代价是:

页数增加 → 页表项增加 → 页表更大。


五、题型三:动态分区分配算法

这是典型的“画内存图”问题。

需要掌握:

算法选择
First Fit 首次适应第一个够大的
Next Fit 邻近/循环首次适应从上次搜索位置继续
Best Fit 最佳适应最小但够用的
Worst Fit 最坏适应最大的

六、经典真题:Best Fit

【2010 408 真题】

题目给出:

主存 55MB,开始全部空闲,采用最佳适应算法:

分配 15MB

→ 分配 30MB

→ 释放 15MB

→ 分配 8MB

→ 分配 6MB

问最后最大的空闲分区是多少。(Any Docs)

开始:

分 15:

再分 30:

释放 15:

空洞为:

申请 8MB。

Best Fit 找最小但够用的。

所以使用 10MB:

现在:

再申请 6MB。

使用 15MB:

最终:

所以最大空闲区:


七、为什么 Best Fit 反而容易产生碎片?

【2019 408 真题】

问:

First Fit、Worst Fit、Best Fit、Next Fit 中,谁最容易产生小碎片?

答案是:

因为它总挑“刚刚够大”的。

例如申请 99KB。

存在:

100KB、300KB、1000KB。

Best Fit 会拿 100KB:

于是不断制造:

1KB、2KB、3KB……

这种很难再使用的小洞。(Any Docs)


八、动态分区真正难的是“释放后合并”

【2017 408 真题】

题目给出的空闲区包括:

20K 起始、40KB;

500K 起始、80KB;

1000K 起始、100KB;

200K 起始、200KB。

现在回收:

起始 60K、大小 140KB。

最好的方法不是靠想象,而是全部写成左闭右开区间。

原第一个:

回收:

后面的空闲分区:

三段刚好连续。

合并:

大小:

于是原来的四个空洞中,两个与新释放区域合并,最终只有三个空洞。

而题目还说明使用 Best Fit 且每次重新排序,所以空闲链表按大小从小到大:

80KB

→ 100KB

→ 380KB。

因此链首是:

起始 500K、80KB。(Any Docs)

这类题的统一方法

永远写:

然后检查:

前一个结束地址 = 新区起始?

新区结束地址 = 后一个起始?

是就合并。

比画随意的方块可靠得多。


九、模拟题的重要变式:从高地址端分配

本站里有一道王道模拟题:

初始用户区 [126K,512K),所有申请都从所选空闲分区的高地址端切出。

依次申请、释放后再采用 First Fit,最终最小空闲块得到 13KB。(Any Docs)

这道题最有价值的地方不是答案,而是在提醒:

“First Fit”只决定选哪个空洞,并不一定决定从空洞哪一端切。

如果题目明确:

“从高地址部分分配”

就不能习惯性从低地址端画。


十、伙伴算法:2024 已经正式考过

【2024 408 真题】

题目问:

每次释放分区时,只与“大小相同的对应空闲分区”进行合并的是哪种算法?

答案:

伙伴系统的块大小都是:

例如申请 20KB。

可能从 64KB 开始:

给用户一个 32KB。

内部浪费:

释放以后,只有它对应的那个 32KB 伙伴也空闲,才能合并:

不能随便找另一个 32KB 合并。(Any Docs)

这可能继续变式

408 很可能继续考:

给起始地址、块大小,判断两个块是不是 buddy;

或者连续申请、释放后求最终空闲块。

这属于值得准备的新考法。


十一、题型四:基本分页——本章真正的核心

分页系统有三个词必须彻底区分:

概念属于哪里
page 页虚拟地址空间
frame 页框 / 页帧 / 物理块物理内存
page table 页表page → frame 映射

例如:

虚拟页 5 → 页框 17。

如果页面大小为 4KB:


十二、地址位数怎么拆?

如果页大小为:

那么页内偏移 12 位。

32 位地址:

因此:

虚拟页数:

页面:


十三、页表大小怎么算?

假设:

32 位虚拟地址;

页大小 4KB;

PTE 4B。

页号 20 位,所以页表有:

项。

每项 4B:

所以一个进程如果建立完整一级页表,就可能需要 4MB。

这正是多级页表出现的原因之一。


十四、2013 408 大题:必须会

【2013 408 真题】

题目给定:

32 位逻辑地址和物理地址;

页表项 4B;

一级分页中地址格式为:

20 位页号 + 12 位页内偏移;

然后又改为:

10 位页目录号 + 10 位页表索引 + 12 位页内偏移;

最后给代码段逻辑地址和页表起始物理地址,要求继续算页表项地址和物理页框。(Any Docs)

这道题几乎就是分页计算的模板题。


第1问:页多大?

低 12 位偏移:


页表最大多大?

页号 20 位:

个页表项。

每项 4B:


第2问:二级页表地址拆分

地址:

对于虚拟地址 LA:

页目录号:

页表索引:

因为:

正好取得 10 位。


第3问:页表项物理地址

如果代码从:

00008000H

开始。

页大小:

1000H

因此:

属于虚页 8。

下一个页是虚页 9。

若页表从:

00200000H

开始,每个 PTE 为 4B。

虚页 8 的 PTE:

虚页 9:

这一招非常重要:

以后所有一级页表题本质一样。


十五、为什么要多级页表?

【2014 408 真题】

题目问多级页表的优点。

正确方向不是“转换更快”,而是:

减少页表对大块连续内存的要求,并且没用到的虚拟地址范围可以不建立下级页表。(Any Docs)

这一点非常容易错。

多级页表:

节省页表空间 / 降低连续空间要求

但代价是:

地址转换可能访问更多次内存。

例如没有 TLB:

一级页表:

查页表 + 访问数据:

次内存。

二级页表:

页目录

→ 二级页表

→ 数据。

一共:

次。

三级:

次。

因此:


十六、二级页表的经典计算

【2010 408 真题】

条件:

页面:

PTE:

2B。

整个逻辑空间:

页。

一个二级页表通常占一个页面,所以每张二级页表能放:

个 PTE。

总共需要管理:

页。

因此需要二级页表数量:

于是页目录至少有:

项。(Any Docs)

通用公式

页面大小 ,PTE 大小 :

如果要覆盖 个页面:


十七、多级页表最少要几级?

这是模拟题很好的补充。

【王道·卷八 Q27】

实际虚拟地址空间为:

页面:

PTE:

问至少几级页表。(Any Docs)

页内偏移:

位。

虚拟页号:

位。

一个页表页可以容纳:

个 PTE。

所以一级可以承担 10 位索引。

35 位 VPN 需要:

级。

因此:

统一公式

若:

虚拟地址有效位数 =

页面大小 =

PTE 大小 =

则每张页表可放:

项。

一级能索引:

位。

VPN:

位。

页表级数:

这是非常值得记住的推导式。


十八、PDBR / 页表基址寄存器到底存什么?

【2021 408 真题】

二级分页系统问:

CPU 页表基址寄存器保存什么?

答案:

不是虚拟地址。(Any Docs)

为什么?

假如 PDBR 存虚拟地址:

CPU 想查页表

→ 得先把 PDBR 的虚拟地址转物理地址

→ 转它又需要查页表

→ 但页表地址还不知道……

循环依赖。

所以必须从一个真实物理地址起步。


十九、进程切换与线程切换对 PDBR 的影响

【2018 408 大题】

题目还问:

进程切换时 PDBR 变不变?

同一进程线程切换时呢?

结论:

不同进程有不同虚拟地址空间:

同一进程中的线程共享虚拟地址空间:

这道题同时还要求由页目录号、页号和偏移重新拼出虚拟地址,以及说明改进 CLOCK 需要访问位和修改位。(Any Docs)


二十、题型五:分段

分页:

站在操作系统/物理内存角度,把东西等大小切。

分段:

站在程序员逻辑角度,把程序分成代码段、数据段、栈段……

所以分段地址:


二十一、最大段长怎么求?

【2009 408 真题】

32 位逻辑地址。

段号占 8 位。

于是段内偏移占:

位。

所以单段最大长度:

注意:

最大合法偏移是:

但“最大段长度”是:

不要差 1。(Any Docs)


二十二、分段地址转换:先越界检查!

【2016 408 真题】

段 2:

段长 300;

基址 4000;

已经在内存;

可读写。

现在访问:

段号 2,段内地址 400。

有人会直接算:

错。

必须先检查:

不成立。

因此直接:

不会得到 4400。(Any Docs)

统一流程:


二十三、共享段 / 共享页

这是近年来非常值得注意的一类。

【2019 408 真题】

P1 和 P2 共享段 S。

共享意味着:

物理内存中只保存一份。

但:

因为段号属于各自的逻辑地址空间。(Any Docs)


【2023 408 真题】

进一步改成分页。

R 和 S 共享数据 data。

在 R 中虚拟页号为 ,在 S 中为 。

对应页框:

。

因为两个进程虚拟地址空间独立:

和

不必一样。

但既然共享同一份物理数据:

所以:

这是理解虚拟内存非常好的一道题。(Any Docs)


二十四、题型六:请求分页与缺页异常

这是第二大核心。

基本分页:

所有需要页面先装进来,再运行。

请求分页:

暂时不用的页面先不装,访问到了再装。

所以页表项必须额外记录:

存在位 / 有效位。

例如:

页号页框号存在位
2171
3—0

访问页 3:


二十五、缺页异常到底干什么?

完整逻辑是:

虚拟地址合法

→ 查页表发现页面不在内存

→ 产生缺页异常

→ OS 接管

→ 找页框

→ 必要时选择牺牲页

→ 若牺牲页已修改则写回

→ 从磁盘调入目标页

→ 修改页表

→ 必要时更新/失效 TLB

→ 重新执行发生缺页的指令

这里一个非常关键的判断:

缺页 ≠ 越界

缺页表示:

越界表示:


二十六、缺页时一定置换页面吗?

不是。

【2022 408 真题】

页面 b 不在内存,发生缺页。

问缺页处理“不一定”包含什么操作。

答案:

因为如果还有空闲页框:

直接把 b 放进去即可。

无须淘汰。(Any Docs)

所以:

缺页:

页面置换。

正确关系是:


二十七、固定分配、可变分配、局部/全局置换

【2015 408 真题】

问哪种组合不可能:

固定分配 + 全局置换。

答案:

原因:

固定分配规定:

进程页框数固定。

全局置换:

可以从系统其他进程占用的页框里选牺牲页。

那某进程拿走别人的页框之后,各进程页框数就改变了。

于是与固定分配矛盾。(Any Docs)

应该记:

组合可否
固定 + 局部✓
固定 + 全局✗
可变 + 局部✓
可变 + 全局✓

二十八、题型七:页面置换算法

四个必须精通:

算法淘汰谁需要什么信息
OPT未来最久不用未来访问序列
FIFO最早进入内存装入时间
LRU最久没有被访问最近访问历史
CLOCK近似 LRU访问位
改进 CLOCK综合访问/修改A 位 + M 位

二十九、OPT:理论最优

OPT:

未来最长时间不用的页面淘汰。

它能取得理论上的最少缺页次数。

但真实系统不知道未来。

所以:


三十、FIFO:只看“进来多久”

例如内存:

A 在时刻 10 装入;

B 在 20;

C 在 30。

现在缺页。

FIFO:

因为 A 最早进入。

它根本不管:

A 刚刚是不是被访问了。


三十一、LRU:只看“多久没使用”

例如最近访问:

A:时刻 100

B:时刻 80

C:时刻 120

那么:

因为 B 最近一次使用离现在最远。


三十二、2015 408:LRU 标准选择题

分配 4 个页框。

访问序列已经走到:

2,0,2,9,3,4,2,8,2,4,8,4,5。

下一页是 7。

题目问 LRU 淘汰谁。(Any Docs)

处理完成后驻留:

看它们最后一次出现的位置。

2:更早

8:之后

4:之后

5:刚刚出现。

所以:

LRU 最快方法

如果题目只问“当前淘汰谁”,不一定需要从头完整画表。

只要确定当前驻留页面,然后从访问序列末尾倒着找。

最后最晚找到的那个驻留页,就是 LRU。


三十三、FIFO 与 LRU 最容易混淆的地方

假设:

A 最早装入;

但 A 刚刚被访问。

那么:

FIFO:

仍然淘汰 A。

LRU:

不会淘汰 A。

一句口诀:

FIFO 看出生日期,LRU 看最后活动时间。


三十四、Belady 异常

【2014 408 真题】

现象:

页框增加以后,缺页次数反而增加。

可能发生在:

LRU 和 OPT 不会。(Any Docs)

考试记:

因为 LRU、OPT 具有栈性质。


三十五、CLOCK 算法

每个页面有访问位 A。

访问页面时:

缺页需要淘汰时,从指针开始扫描:

如果:

直接淘汰。

如果:

给第二次机会:

指针继续走。

所以也叫:

Second Chance 第二次机会算法。


三十六、2010 408 大题:FIFO 与 CLOCK

这道题非常值得完整掌握。

【2010 408 真题】

页大小:

进程当前 4 个页面:

页页框装入时刻A
071301
142301
222001
391601

访问逻辑地址:

17CAH。(Any Docs)


第一步:拆页号

所以:

页 5 不在内存,缺页。


第二问:FIFO

装入时间:

页 0:130

页 1:230

页 2:200

页 3:160。

最早:

所以淘汰页 0。

页 0 原页框:

页 5 装入页框 7。

物理地址:


第三问:CLOCK

指针当前指向页框 2。

所有页面 A 都是 1。

第一次扫描:

全部从 1 清成 0。

转一圈重新回到页框 2。

现在该页:

于是淘汰页框 2 中的页 2。

页 5 装入页框 2。

物理地址:

这道题体现了本章的核心综合形式:


三十七、改进型 CLOCK

普通 CLOCK 只考虑:

访问位 A。

改进 CLOCK 再加入:

修改位 M。

四种组合:

AM含义
00最近没访问、没修改
01最近没访问、修改过
10最近访问、没修改
11最近访问、修改过

理想淘汰顺序考试中记:

为什么 (0,0) 最好?

没访问:

说明近期不重要。

没修改:

意味着和磁盘中的副本一致。

所以可以直接扔。


为什么 M=1 代价大?

因为页已经被改过。

内存:

新版本。

磁盘:

旧版本。

淘汰前必须:

产生额外 I/O。

2016 真题就直接考过四类的淘汰次序。(Any Docs)


三十八、2021 408:缺页 + 改进 CLOCK + 地址转换

题目给:

页大小 4KB;

2 个固定页框;

页 3:

存在,

页 4:

存在,

页 2:

不存在。

现在访问:

02A01H。(Any Docs)

拆地址:

所以访问页 2。

页 2 不在内存:

缺页。

改进 CLOCK 经过扫描后优先让页 3 成为:

因此淘汰页 3。

页 3 原页框:

所以页 2 装入 60H。

物理地址:

最重要的坑是:

页 2 页表项里即使残留了一个旧页框号,只要存在位为 0,这个页框号就不能直接用于地址转换。


三十九、FIFO、LRU、CLOCK 怎么做得最快?

模拟题中有一道非常适合练“读表判断”:

给出每页:

装入时间;

最近访问时间;

访问位;

修改位。

然后同时问 FIFO、LRU、改进 CLOCK 淘汰谁。(Any Docs)

只需要看对应字段:

算法看哪个字段
FIFO装入时间最小
LRU最近访问时间最小
改进 CLOCKA、M,并结合指针扫描顺序

千万不要拿“最近访问时间”做 FIFO。

也不要拿“装入时间”做 LRU。


四十、题型八:工作集

工作集:

某一段最近的访问窗口内,进程访问过的不同页面集合。

设窗口大小为 。

工作集:

就是时刻 前最近 次/时间单位涉及的不同页面。


【2016 408 真题】

访问序列在 t 前最后 6 次为:

6,0,3,2,3,2。

窗口大小 6。

去重:

注意:

窗口 6 ≠ 工作集大小 6。

窗口内有重复页。

因此:

而不是 6。(Any Docs)


四十一、抖动 Thrashing

这是概念题非常爱考的。

抖动:

CPU 大量时间都在处理缺页和换页,真正执行程序的时间很少。

常见原因:

进程太多:

每个进程得到的页框太少。

工作集装不下。

于是:

A 缺页

→ 换 B

→ 马上访问 B

→ 又换 A

→ 又要 A……

磁盘疯狂 I/O。


【2011 408 真题】

题目给三个方案:

撤销部分进程;

增加交换区;

提高进程优先级。

有效措施是:

因为可以减少多道程序度,让剩余进程得到更多页框。

单纯扩大 swap:

并不能让进程的工作集装进物理内存。

提高优先级也不能增加它的驻留集。(Any Docs)


四十二、工作集与抖动本质联系

如果进程 当前工作集大小:

所有进程总工作集需求:

如果物理页框总数为 。

当:

说明系统无法同时容纳所有活跃进程当前真正需要的页面。

于是很容易:

所以解决思路:

降低:

最直接就是减少活跃进程数。


四十三、题型九:TLB

TLB 可以理解成:

页表的 Cache。

页表在内存中。

如果每次访问数据都:

先查页表

→ 再访问数据,

一次逻辑访存变成两次物理访存。

所以把近期常用的:

缓存到高速 TLB。


四十四、没有 TLB 与有 TLB

设:

TLB 查询:

内存:

一级页表。

如果 TLB 命中:

如果 TLB 未命中,并且 TLB 与内存页表不是并行访问:

平均时间:

其中 是 TLB 命中率。


四十五、模拟题:反推 TLB 命中率

本站有一道很好的模拟题:

TLB 查询 1ns;

内存访问 100ns;

TLB 与页表查询并行;

要求开启分页以后平均访存时间不超过 110ns。

求最低 TLB 命中率。(Any Docs)

命中:

TLB 1ns 得到结果,然后访问数据:

未命中。

因为 TLB 与内存中的页表同时开始查:

100ns 时页表完成,

然后再访问一次目标数据:

设命中率 :

整理:

这种题最关键的不是公式背诵,而是先判断:

TLB 和页表是串行查,还是并行查?

题目条件不同,公式就不同。


四十六、超级经典:2009 TLB + 缺页 + LRU 综合大题

这是第 3 章非常值得反复做的一道题。

【2009 408 真题】

页大小:

4KB。

页表部分情况:

页 0 → 101H,有效;

页 1 → 不在内存;

页 2 → 254H,有效。

TLB 初始为空。

TLB:

10ns。

内存:

100ns。

一次缺页:

驻留集固定为 2;

使用 LRU。

访问:

2362H

→ 1565H

→ 25A5H。(Any Docs)


第一次:2362H

访问页 2。

页 2 在内存,但 TLB 空。

所以:

查 TLB:

10ns;

TLB miss;

查内存页表:

100ns;

访问目标数据:

100ns。

总时间:

同时页 2 进入 TLB。


第二次:1565H

访问页 1。

TLB miss:

10ns。

查页表:

100ns。

发现存在位 0。

到这一刻:

产生缺页。

缺页处理:

因为驻留集固定为 2:

当前页 0 和页 2 在内存。

刚刚访问过页 2。

LRU 淘汰:

页 1 被装入页 0 原来的页框:

处理完成以后:

重新执行发生缺页的指令。

题目说明缺页处理已经更新 TLB。

于是重执行:

TLB 命中:

总计:

应从这个数字直观感受到:

一次缺页的代价比普通内存访问大好几个数量级。


第三次:25A5H

页 2。

页 2 仍在内存,并且 TLB 已经缓存映射。

所以:


页 1 的最终物理地址

页 1 被装入:

页框。

所以:

这道题一定要掌握什么?

它实际上把五个点串在了一起:

TLB

→ 页表

→ 缺页

→ LRU

→ 物理地址。

以后看到复杂大题就按这个顺序拆开,而不是试图一口气想完。


四十七、有效访存时间 + 缺页率

设正常访存时间:

缺页率:

一次缺页处理的额外代价:

则近似:

因为:

很多题近似写成:


四十八、模拟题:反推最大缺页率

本站有一道很有价值的模拟题:

正常内存访问 1μs;

未修改页缺页处理 1ms;

修改页缺页处理 10ms;

60% 被换出的页面修改过;

要求 EAT 不超过 3μs。(Any Docs)

平均缺页处理时间:

转成 μs:

正常分页访问约为:

于是:

因此:

这类题透露出一个非常重要的考试直觉:

允许的缺页率往往必须极低。

因为磁盘 I/O 太慢。


四十九、为什么修改位这么重要?

假设替换一个干净页面。

磁盘里已经有正确副本。

可以直接:

丢掉。

但修改页:

内存是最新版本。

所以必须:

于是一次置换可能发生:

两次磁盘 I/O。

所以所有置换算法都倾向于:

在条件相近时优先淘汰干净页。


五十、题型十:缺页次数和页面置换次数不能混

【2019 408 真题】

进程预分配 4 个页框,LRU,访问:

0,1,2,7,0,5,3,5,0,2,7,6。

问:

页面置换次数,不是缺页次数。(Any Docs)

前四个页面:

0,1,2,7

都是缺页。

但是页框还空着。

所以:

之后访问新页才开始淘汰。

最终置换:

5 次。

所以必须区分:

开始填充空页框时:

有缺页,没有置换。


五十一、题型十一:页面缓冲算法

本站模拟题专门补充了页面缓冲。(Any Docs)

核心思想:

被淘汰的页不要立刻彻底处理掉。

例如干净页放进:

空闲页面链。

脏页放进:

修改页面链。

如果刚淘汰不久又访问它,而且原页框还没被重新利用:

就可以快速拿回来。

这利用的仍是:


一个很容易出的陷阱

页面缓冲可以:

减少实际磁盘 I/O;

缩短缺页处理代价。

但:

不一定改变“逻辑上有没有发生缺页”。

2022 真题就从另一角度考:

页面缓冲队列长度不会直接决定缺页率,而页面置换算法、工作集、系统进程数量都可能影响缺页率。(Any Docs)

一定区分:

与:

这是两个不同指标。


五十二、2012 408 大题:页面缓冲 + 时间局部性

这道真题给出:

每隔 5 个时间单位扫描驻留集;

本轮没访问的页面回收到空闲页框链尾;

但页框内容暂时不清空;

如果以后又访问且原内容还在,就重新拿回来。(Any Docs)

例如页 1 原来占页框 32。

后来因为一个扫描窗口内没访问,被回收到空闲链。

但内容仍然是页 1。

随后很快再次访问页 1。

那么系统发现:

32 号页框里的旧内容还没有被覆盖。

可以直接恢复:

号页框。

不需要磁盘重新读。

所以这种策略特别适合:


五十三、题型十二:程序局部性

这是这几年特别值得重视的交叉知识点。

局部性分:

时间局部性:

刚访问过的东西很可能很快再次访问。

空间局部性:

访问某地址以后,很可能继续访问附近地址。

分页、TLB、Cache 都大量依赖局部性。


五十四、数组按行还是按列?

【2020 408 大题】

数组:

a[1024][1024]

每个元素 4B。

起始虚拟地址:

10800000H。

题目问:

a[1][2] 的虚拟地址;

页目录号、页号;

页目录项和页表项地址;

虚拟空间/物理空间是否连续;

最后还问按行遍历和按列遍历哪个局部性好。(Any Docs)


a[1][2] 地址

C 语言二维数组行优先。

前面经过:

个元素。

每个 4B:

所以虚拟地址:


五十五、二维数组地址通式

对于:

A[M][N]

元素大小 。

0 下标时:

如果题目用 1 下标,要特别修改。


五十六、为什么按行遍历好?

数组按行存储。

同一行:

A[i][0], A[i][1], A[i][2]...

地址连续。

所以按行访问:

而按列:

A[0][j]

→ A[1][j]

→ A[2][j]

每次跨越一整行。

这道 2020 真题中:

一行大小:

恰好一页。

所以按列每访问下一元素:

几乎就跳到下一页。

极易:

TLB miss

  • Cache miss

  • 甚至缺页。

而按行可以连续吃完整个页面。(Any Docs)


五十七、模拟题把这一点考得更极端

【王道·卷二 Q29】

数组:

128×128。

一页正好放 128 个数组元素。

进程工作集只有两个页框。

代码占 1 个。

数据事实上只剩:

个页框。

程序 1 按列扫描;

程序 2 按行扫描。(Any Docs)

按列:

每访问一个元素都跳到另一页。

大约:

次缺页。

按行:

一行正好一页。

每行只第一次访问缺页:

次。

两者差距:

这就是“代码写法本身影响虚拟内存性能”的经典考法。


五十八、虚拟地址连续 ≠ 物理地址连续

仍然是 2020 真题。

数组在 C 程序中:

逻辑上连续。

所以它在虚拟地址空间需要连续。

但相邻虚页可以:

页 100 → frame 8

页 101 → frame 999

页 102 → frame 17。

所以物理页框完全可以离散。

因此:

这恰恰是分页的重要价值。


五十九、虚拟内存容量到底由什么决定?

这是非常高频的错误说法。

有人说:

虚拟内存大小 = 内存 + 硬盘。

不严谨。

理论虚拟地址空间首先受:

约束。

例如 32 位虚拟地址:

地址空间。

2023 真题直接考过:

虚拟地址空间大小不是由“物理内存 + 硬盘大小”决定。(Any Docs)

所以:

swap 只是虚拟内存实现中的后备存储资源之一。


六十、一道非常容易忽略的题:最少要几个页框?

模拟题:

指令系统允许一级间接寻址;

请求分页;

问一个进程至少需要多少页框才能保证指令完成。(Any Docs)

最坏情况:

一条指令本身跨两个页面:

页。

一级间接寻址的间接地址:

可能另占:

页。

最终操作数:

又在另一个页面:

页。

所以至少:

个页框。

这种题不是普通地址计算,而是在问:

一条指令执行过程中最多需要同时存在多少个页面?

属于很好的拓展题型。


六十一、多级页表综合题怎么拆?

以后遇到:

32 位地址:

只要看到虚拟地址:

0xXXXXXXXX

立刻拆:

页目录:

二级页表索引:

offset:


六十二、页目录项地址怎么算?

页目录基址:

页目录号:

每项 4B。

那么:

查 PDE 得到二级页表页框:

于是二级页表基址:

页表索引:

所以:

再查 PTE:

得到数据页框 。

最终:

这套链条一定要非常熟:


六十三、整个第 3 章综合大题统一做题模板

以后不管题面多长,都按下面这个顺序。

步骤做什么
1先确定页面大小,得到 offset 位数
2把虚拟地址拆成页号/各级索引/offset
3先查 TLB,判断 hit / miss
4TLB miss 再按层级查页表
5检查存在位、权限、越界等控制位
6缺页则判断有没有空页框
7没空页框时应用 FIFO/LRU/CLOCK 等
8脏页需要写回,随后调入新页
9更新页表、TLB、相关状态位
10重新执行发生缺页的指令
11得到页框号后拼接 offset
12如果问时间,再把各次 TLB/内存/磁盘访问逐项相加

看到复杂题不要慌。

本质上永远只是这条流水线。


六十四、几个特别容易丢分的“不是一回事”

概念 A概念 B区别
页 page页框 frame虚拟 vs 物理
缺页页面置换有空页框时缺页但不置换
TLB miss缺页TLB 没有不代表内存没有
缺页越界合法但不驻留 vs 地址非法
页号页框号虚拟编号 vs 物理编号
虚拟地址连续物理地址连续前者完全可以对应离散页框
FIFOLRU装入时间 vs 最近访问时间
缺页率缺页处理时间发生概率 vs 一次处理代价
页表TLB完整映射结构 vs 高速缓存
虚拟地址空间swap地址范围 vs 外存后备空间
内部碎片外部碎片已分配内部浪费 vs 空闲空间零散

这张表建议反复看。


六十五、TLB miss、page fault 的完整关系

这也是经常理解错的地方。

情况 A:TLB hit

TLB:

有映射。

直接得到 frame。

通常不查内存页表。


情况 B:TLB miss,但页表有效

TLB 没缓存。

但页面其实在物理内存。

于是:

TLB miss

→ 查页表

→ 得到 frame

→ 更新 TLB

→ 访问数据。

没有缺页。


情况 C:TLB miss,页表存在位 0

TLB miss

→ 查页表

→ 发现不驻留

→ page fault。

所以关系:

但在一般设计下发现 page fault 前通常要查到相关页表状态。


六十六、页面大小变大,到底有什么影响?

这是很适合出综合选择题的知识点。

页面变大:

页数减少。

因此:

页表更小。

TLB 每个表项覆盖范围扩大。

磁盘顺序传输效率可能提高。

但是:

内部碎片一般增大。

一次调入的数据更多。

如果空间局部性差,会装进很多无用数据。

所以没有:

“页面越大一定越好”

或:

“页面越小一定越好”。

408 最喜欢这种绝对化选项。


六十七、一个很实用的平均内部碎片结论

如果进程大小相对页面边界可以近似认为随机。

最后一页平均浪费:

其中 为页大小。

所以页面越大:

平均内部碎片一般越大。

这个虽然不一定每次直接考公式,但非常适合用来判断选项。


六十八、缺页异常属于什么?

缺页通常属于:

它由当前正在执行的指令访问虚拟地址引起。

磁盘完成页面读入以后产生的完成通知则属于:

一道综合题完全可能把第 2 章异常/中断和第 3 章虚拟内存结合起来。


六十九、为什么缺页后要重新执行指令?

假设执行:

x = A[i];

CPU 执行到访问 A[i]:

发现页面不存在。

此时这条指令还没真正完成。

OS 调入页面以后不能直接执行下一条。

必须:

这也是计算一次缺页总时间时经常忘掉的一部分。

2009 那道综合真题就明确利用了这一点。


七十、数组题还可能和 Cache 联合

这是非常值得预测的一种 408 综合考法。

已经有真题把:

二维数组

  • 分页

  • 二级页表

  • 局部性

放在一起。

后续完全可以继续加入:

Cache。

例如:

页面 4KB;

Cache block 64B;

数组元素 4B。

一个页面有:

个 int。

一个 Cache block 有:

个 int。

如果顺序遍历:

每 16 个 int 一次 Cache 块缺失;

每 1024 个 int 一次新页。

因此一个循环可以同时问:

Cache miss

  • TLB miss

  • page fault。

这种组合非常符合 408 “计组 + 操作系统交叉”的风格。


七十一、伙伴算法也可能和碎片一起升级

2024 已经明确考 Buddy。

下一步值得防的题:

给:

总内存 1MB;

最小块 4KB;

依次申请:

70KB、130KB、20KB……

要求写出实际分配块大小。

例如申请 70KB:

最近的 :

所以内部浪费:

这能把:

伙伴系统

  • 内部碎片

  • 地址对齐

组合起来。


七十二、还有一种值得防:Copy-on-Write

虽然传统基础教材不会把它当本章最核心内容,但它和近年的“共享物理页”题非常自然。

例如 fork 后:

父进程页

子进程页

一开始都映射:

于是:

完全可以,而:

当某个进程写页面时发生保护异常,OS:

复制物理页

→ 修改该进程页表

→ 以后两个进程页框不同。

这本质上就是 2023“共享数据页”考法的自然延伸。


七十三、从本站里的真题分布来看,应该怎么复习?

本章不要平均用力。

最应该反复训练的是下面四条链。

第一条

这是基础。

第二条

这是多级页表。

第三条

这是综合大题。

第四条

这是性能分析题。


七十四、最后给出压缩成考场判断口诀

分区:

固定有内碎,动态有外碎;

Best Fit 小洞多;

回收先看前邻后邻;

紧凑需要动态重定位。

分页:

页号在高位,偏移在低位;

offset 位数决定页大小;

页表基址 + 页号 × PTE 大小;

物理地址 = 页框 × 页大小 + offset。

多级页表:

上一级 PTE 指向下一级页表的物理页框;

多级页表省页表空间,不是为了加快访问;

没有 TLB,级数越多访存次数通常越多;

PDBR 指向最高级页表的物理地址。

分段:

先查段号;

再查 offset 是否越过段长;

再看权限;

最后才是 base + offset。

虚拟内存:

缺页是“合法但不在内存”;

有空页框不一定置换;

脏页换出要写回;

缺页后重新执行原指令。

置换算法:

FIFO 看谁最早进;

LRU 看谁最久没用;

CLOCK 看 A;

改进 CLOCK 看 A、M;

FIFO 可能 Belady。

共享:

虚页号可以不同;

共享物理页框必须相同。

局部性:

C 二维数组按行存;

按行遍历通常远好于按列。


本章最应该真正做会的真题

如果时间有限,第 3 章建议至少把这些题真正拿纸完整算一遍:**2013 分页/二级页表大题、2009 TLB+缺页+LRU 大题、2010 FIFO/CLOCK 大题、2012 页面缓冲大题、2015 多级页表大题、2018 PDBR/地址组成大题、2020 二维数组+二级页表大题,再配 2021 改进 CLOCK 和 2023 共享页选择题。**它们基本覆盖了内存管理最重要的命题骨架。本站中的真题也确实持续围绕这些主题反复变化。(Any Docs)

如果只记这一章最重要的一句话,就是:

这条思路真正熟练以后,第 3 章那些看起来很长的综合大题,实际上都只是把几个固定步骤串起来。

On this page

一、先建立整章知识地图二、整章最重要的“地址转换模型”三、题型一:链接、装入、重定位与地址保护1. 逻辑地址什么时候形成?【2011 408 真题】2. 重定位紧凑为什么需要动态重定位?3. 地址保护【2009 408 真题】四、题型二:内部碎片与外部碎片1. 内部碎片2. 外部碎片必须记住的表五、题型三:动态分区分配算法六、经典真题:Best Fit【2010 408 真题】七、为什么 Best Fit 反而容易产生碎片?【2019 408 真题】八、动态分区真正难的是“释放后合并”【2017 408 真题】这类题的统一方法九、模拟题的重要变式:从高地址端分配十、伙伴算法:2024 已经正式考过【2024 408 真题】这可能继续变式十一、题型四:基本分页——本章真正的核心十二、地址位数怎么拆?十三、页表大小怎么算?十四、2013 408 大题:必须会【2013 408 真题】第1问:页多大?页表最大多大?第2问:二级页表地址拆分第3问:页表项物理地址十五、为什么要多级页表?【2014 408 真题】十六、二级页表的经典计算【2010 408 真题】通用公式十七、多级页表最少要几级?【王道·卷八 Q27】统一公式十八、PDBR / 页表基址寄存器到底存什么?【2021 408 真题】十九、进程切换与线程切换对 PDBR 的影响【2018 408 大题】二十、题型五:分段二十一、最大段长怎么求?【2009 408 真题】二十二、分段地址转换:先越界检查!【2016 408 真题】二十三、共享段 / 共享页【2019 408 真题】【2023 408 真题】二十四、题型六:请求分页与缺页异常二十五、缺页异常到底干什么?缺页 ≠ 越界二十六、缺页时一定置换页面吗?【2022 408 真题】二十七、固定分配、可变分配、局部/全局置换【2015 408 真题】二十八、题型七:页面置换算法二十九、OPT:理论最优三十、FIFO:只看“进来多久”三十一、LRU:只看“多久没使用”三十二、2015 408:LRU 标准选择题LRU 最快方法三十三、FIFO 与 LRU 最容易混淆的地方三十四、Belady 异常【2014 408 真题】三十五、CLOCK 算法三十六、2010 408 大题:FIFO 与 CLOCK【2010 408 真题】第一步:拆页号第二问:FIFO第三问:CLOCK三十七、改进型 CLOCK为什么 (0,0) 最好?为什么 M=1 代价大?三十八、2021 408:缺页 + 改进 CLOCK + 地址转换三十九、FIFO、LRU、CLOCK 怎么做得最快?四十、题型八:工作集【2016 408 真题】四十一、抖动 Thrashing【2011 408 真题】四十二、工作集与抖动本质联系四十三、题型九:TLB四十四、没有 TLB 与有 TLB四十五、模拟题:反推 TLB 命中率四十六、超级经典:2009 TLB + 缺页 + LRU 综合大题【2009 408 真题】第一次:2362H第二次:1565H第三次:25A5H页 1 的最终物理地址这道题一定要掌握什么?四十七、有效访存时间 + 缺页率四十八、模拟题:反推最大缺页率四十九、为什么修改位这么重要?五十、题型十:缺页次数和页面置换次数不能混【2019 408 真题】五十一、题型十一:页面缓冲算法一个很容易出的陷阱五十二、2012 408 大题:页面缓冲 + 时间局部性五十三、题型十二:程序局部性五十四、数组按行还是按列?【2020 408 大题】a[1][2] 地址五十五、二维数组地址通式五十六、为什么按行遍历好?五十七、模拟题把这一点考得更极端【王道·卷二 Q29】五十八、虚拟地址连续 ≠ 物理地址连续五十九、虚拟内存容量到底由什么决定?六十、一道非常容易忽略的题:最少要几个页框?六十一、多级页表综合题怎么拆?六十二、页目录项地址怎么算?六十三、整个第 3 章综合大题统一做题模板六十四、几个特别容易丢分的“不是一回事”六十五、TLB miss、page fault 的完整关系情况 A:TLB hit情况 B:TLB miss,但页表有效情况 C:TLB miss,页表存在位 0六十六、页面大小变大,到底有什么影响?六十七、一个很实用的平均内部碎片结论六十八、缺页异常属于什么?六十九、为什么缺页后要重新执行指令?七十、数组题还可能和 Cache 联合七十一、伙伴算法也可能和碎片一起升级七十二、还有一种值得防:Copy-on-Write七十三、从本站里的真题分布来看,应该怎么复习?第一条第二条第三条第四条七十四、最后给出压缩成考场判断口诀本章最应该真正做会的真题