news 2026/9/30 11:50:49

操作系统408复习:进程/内存/文件/I/O计算链路

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
操作系统408复习:进程/内存/文件/I/O计算链路

操作系统这门课,我在不同阶段完整过了三遍:大二为了期末、大三为了408、后来读研又陪着学弟学妹复盘了一遍。三次下来最深的体会是,它根本不是一门"背多分"的课。真正拉开差距的,是你能不能把进程调度、地址翻译、页面置换、索引结点这几条计算链路闭着眼推出来,而不是看到"操作系统"四个字就先想到一堆名词解释。这份笔记最早是照着王道那套单科书和讲义一句句抄的,抄完发现还是不会做题,于是索性推翻重写,改成"骨架层 + 公式层 + 题眼层"的三层结构:先搭知识地图,再锁死可手算的公式,最后把每道题埋的坑单独标出来。下面这些内容适合三类人——正在准备408的、下周就要考操作系统的、以及想把这门课真正吃透而不是应付考试的人。整篇围绕进程管理、内存管理、文件系统与I/O四条主线展开,每条主线都给出可复现的手算套路和我自己踩过的坑,能直接拿去对答案的那种。

1. 先把"考什么"钉死:操作系统复习无效的三种典型姿势

1.1 为什么把书看三遍,大题还是写不出来

我见过太多人,包括曾经的我,复习操作系统的方式就是"从头读到尾,读完再读一遍"。这种读法的产物是:选择题眼熟得很快,一到大题就卡壳。原因不复杂——选择题考的是"你认不认识这个词",大题考的是"你能不能走完一条完整的推理链路"。比如"分页存储管理",选择题只问你页表存什么,大题却要你从逻辑地址出发,拆页号、查页表、拼物理地址,中间还夹一个TLB命中判断和缺页处理。你光知道"页表是页号到物理块号的映射",这条链路一步都走不动。

所以我的第一个建议很直接:复习操作系统时,凡是能用计算链路串起来的知识点,一律不许用阅读的方式过,必须动手把链路写一遍。进程调度要写时间轴表格,页面置换要画页框快照,地址翻译要写二进制拆位,文件索引要列求和式。写一次的记忆强度,顶得上读五遍。王道那本书的课后大题就是为这个过程准备的,不做题等于没学。

1.2 408和期末考对同一知识点的权重完全不同

这是很多人栽的第二个跟头:拿期末考的复习思路去应付408,或者反过来。两者重合度大概七成,但重心差得很远。我整理了一张对照表,复习前先看清自己在准备哪一场。

知识点期末考常见权重408常见权重建议策略
进程与线程概念、状态转换高中记判定规则即可,不必深挖
调度算法手算中高必须能画时间轴、算带权周转
PV操作与同步互斥高高两类考试都躲不开,重点中的重点
死锁与银行家算法中高安全性序列必须手推熟练
分页/分段地址计算中高多级页表和TLB是高频大题
页面置换算法高高缺页率统计要能画表
文件索引结点计算低高期末常略过,408几乎年年考
磁盘调度算法中中会算磁头移动总量就够
I/O控制方式对比高中适合做表格记忆

提示:如果你的目标是期末,把表格里"期末考权重"高而"408权重"低的行优先吃透;如果是408,把索引结点、多级页表这两块单独拎出来加练,它们是最容易被低估的失分点。

1.3 笔记的三层结构:骨架层、公式层、题眼层

抄书式笔记最大的问题是"信息密度均匀",每一页看起来都同样重要,结果考前一翻全是字,抓不住重点。我后来改成了三层:

  • 骨架层:每个章节只写一页纸的框架图,用层级缩进列出"这一章要解决什么问题、分成哪几块、每块的输出是什么"。比如内存管理这一章,骨架就四行:地址翻译、内存分配、虚拟内存、页面置换。
  • 公式层:把所有需要代入数字的公式集中在一处,写明每个符号的含义和单位。这一层是给你在考场上"抄作业"用的,必须背到条件反射。
  • 题眼层:记录每类题型的触发词。看到"求平均周转时间"就自动切到"完成时间减到达时间";看到"主存访问时间"就自动分清是否含TLB时间;看到"最大文件长度"就自动切到"直接块加各级间接块求和"。

这三层分开记的好处是:考前三天你只需要刷题眼层和公式层,考前一天快速扫一遍骨架层,效率比从头翻书高一个数量级。

2. 进程与线程这条主线:状态、调度与"谁发起"的判定逻辑

2.1 五状态转换题的判定口诀:看谁主动

进程状态转换是选择题的常客,也是最容易靠"感觉"做错的一类。我的判定口诀只有一句:判断发起方是进程自己,还是操作系统或外部事件。

  • 就绪到运行:由调度程序发起,进程被动。
  • 运行到就绪:时间片用完或被更高优先级抢占,进程被动,仍具备运行条件。
  • 运行到阻塞:进程自己主动发起,比如请求I/O、申请资源、等待信号量。
  • 阻塞到就绪:外部事件完成(I/O结束、资源可用、信号量V操作),进程被动。
  • 阻塞到运行:不存在,必须经就绪中转。

这套口诀的威力在于排除法。题目里只要出现"阻塞到运行"或者"就绪到阻塞",直接判错,不用犹豫。另一个高频陷阱是"运行到阻塞"和"运行到就绪"的区别:前者进程失去了CPU并且不再具备运行条件,后者进程失去CPU但随时可以被再次调度。这个区别在后面的调度算法和响应时间计算里会反复用到。

顺带提一句,挂起状态(就绪挂起、阻塞挂起)属于外存换入换出的范畴,判定逻辑和上面一致,只是多了"是否在内存"这一维。看到"挂起"两个字,先问自己:它在内存里吗?

2.2 调度算法的手算模板:两种周转时间必须分清楚

调度大题的核心只有两个公式:

  • 周转时间 = 完成时间 − 到达时间
  • 带权周转时间 = 周转时间 ÷ 服务时间

等待时间 = 周转时间 − 服务时间。这三个量算错一个,后面全崩。我一般先把时间轴画成一条横线,按顺序标出每个进程的起止时刻,再回头填表,比直接在脑子里排序稳得多。

拿一组数据练手,四个进程的到达时间和服务时间如下。

进程到达时间服务时间
A07
B14
C21
D44

先算FCFS(先来先服务):A在0到7,B在7到11,C在11到12,D在12到16。周转时间依次为7、10、10、12,平均9.75;带权周转为1、2.5、10、3,平均4.125。

再算非抢占式SJF(短作业优先):t=0时只有A到达,只能先跑A;t=7时B、C、D都已到达,选服务时间最短的C(1),跑7到8;接着B和D服务时间同为4,按到达先后选B,跑8到12;最后D跑12到16。周转时间依次为7、11、6、12,平均9;带权周转为1、2.75、6、3,平均3.19。

对比一下就很清楚:SJF把平均带权周转从4.125压到3.19,但代价是长作业D的等待被拖长,这就是典型的"饿死"风险的来源。考试里如果题目问"哪种算法对短作业有利",答案就是它。

HRRN(高响应比优先)的响应比公式是**(等待时间 + 服务时间)÷ 服务时间**,也就是 1 + 等待时间 ÷ 服务时间。它是非抢占式的,每次调度前重新算一遍所有就绪进程的响应比,选最大的。这个算法的妙处在于兼顾了长作业——等得越久,响应比越高,不会无限期饿死。

时间片轮转(RR)在纸上推演时最容易乱,我的做法是:画一个就绪队列,时间片用完的进程排到队尾,新到达的进程按到达时刻插入队尾,然后一格一格推。别图快,一次推错就得重来。

2.3 上下文切换、系统调用、中断:三个概念的边界在哪

这三个词在选择题里经常混在一起考,但它们的归属层级完全不同。

中断是硬件层面的机制,分为内中断(异常)和外中断。内中断由当前执行的指令引起,比如除零、缺页、系统调用;外中断来自CPU外部,比如时钟中断、I/O完成中断。注意一个反直觉的点:系统调用本质上是内中断(陷阱),它并不是"外中断"。

系统调用是用户程序请求操作系统服务的唯一入口。凡是涉及资源分配、I/O、进程控制的操作,用户程序都做不了,必须通过系统调用陷入内核态。典型的系统调用包括fork、read、write、exec、wait。

上下文切换保存的是处理机现场,包括程序计数器、寄存器、栈指针等。这里有个高频考点:进程切换一定会引起上下文切换,但上下文切换不一定意味着进程切换。同一进程内从用户态切到内核态,也需要保存和恢复现场,但它不改变当前运行的进程。

2.4 进程与线程到底共享什么

线程是调度的基本单位,进程是资源分配的基本单位,这句话谁都背过,但落到"共享什么"上就有人含糊。我列个表,比死记硬背靠谱。

资源同进程内的线程不同进程之间
地址空间共享独立
全局变量、堆共享独立
栈、寄存器、程序计数器各自独立独立
打开的文件、信号量共享独立
进程ID共享不同

一句话记法:除了栈、寄存器和PC,其他基本都共享。这也是为什么多线程编程里,局部变量天然安全、全局变量必须加锁的根本原因——不是语言的规定,是内存模型决定的。

3. 同步互斥与死锁:PV操作从"看得懂"到"写得对"

3.1 信号量题型的四类模板

PV操作是整张卷子里最能体现功力的一类题。我把见过的题目归成四类模板,背模板比背题目有效得多。

第一类是纯互斥。临界区访问共享变量,标准写法是 mutex 初值1,进入前 P(mutex),退出后 V(mutex)。注意P和V必须成对,且V一定在临界区外面——V放错位置是新手最常犯的错,会导致"锁没解开"或者"提前放行"。

第二类是前后驱同步。题目描述"A完成后B才能开始",就在A末尾 V(s)、在B开头 P(s),s初值0。多条依赖链就开多个信号量,一一对应。

第三类是生产者-消费者。标准三信号量写法:mutex=1(互斥访问缓冲区),empty=n(空槽位数),full=0(已有产品数)。生产者的顺序是 P(empty) → P(mutex) → 放入 → V(mutex) → V(full);消费者的顺序是 P(full) → P(mutex) → 取出 → V(mutex) → V(empty)。这里有个铁律:资源信号量(empty/full)必须在互斥信号量(mutex)之前P,反过来写会死锁。原因很简单,如果先占住mutex再等empty,缓冲区满时生产者抱着锁睡觉,消费者永远进不来解这个锁。

第四类是读者-写者。核心是加一个计数器 count 记录当前读者数,第一个读者进来时给写者上锁,最后一个读者离开时解锁。写法是:读者侧 P(mutex) → count++ → 若count==1则P(rw) → V(mutex);读完后再 P(mutex) → count−− → 若count==0则V(rw) → V(mutex)。写者侧直接 P(rw) … V(rw)。

3.2 经典模型怎么改:变体题的加工思路

考试不会原封不动考经典模型,一定加条件。常见改法有三种。

第一种是缓冲区容量变化。原来是n个槽位,改成1个,那就退化成单缓冲,empty和full初值分别为1和0。改成无限容量,可以直接去掉empty信号量——因为永远有空位,不需要等待。

第二种是增加同步顺序约束。比如要求"必须先取再放""同一类操作不能连续超过三次"。这类题的解法是引入额外的计数信号量或者状态标记,把"次数"当成一个需要互斥修改的共享变量,改完再判断是否需要阻塞。

第三种是多类角色加配额。比如"最多允许两个读者同时读"。这时候除了mutex和rw,还要加一个初值为2的读者并发信号量,每个读者进出时P/V它一次。这类题的关键是别把"数量限制"和"互斥"混为一谈——前者用计数信号量,后者用初值1的信号量。

我自己的做法是:拿到题先把所有角色列出来,标出哪些是"资源的消耗者"、哪些是"资源的生产者"、哪些之间是互斥关系、哪些之间是先后关系,画成一张小图,再逐个映射到信号量。这比直接上手写代码快得多。

3.3 死锁判定与银行家算法的手算流程

死锁的四个必要条件是互斥、不可剥夺、请求并保持、循环等待。注意它们是"必要条件",不是充分条件,所以选项中如果出现"满足这四个条件就一定死锁",那是错的。破坏其中任意一个就能预防死锁:破坏请求并保持用资源预分配,破坏不可剥夺用强制回收,破坏循环等待用资源有序分配。

银行家算法的步骤是固定的,照着走不会错:

  1. 算 Need 矩阵,Need = Max − Allocation。
  2. 把 Available 作为初始 Work,把所有进程的 Finish 置为 false。
  3. 在未完成的进程里找一个 Need 小于等于 Work 的,分配给它,执行完回收资源,Work += Allocation,Finish 置 true。
  4. 重复第3步,直到所有进程完成(存在安全序列),或者找不到可满足的进程(处于不安全状态)。

举个简单的例子,三个进程P0、P1、P2,Available = [3, 3, 2],Need 分别是 [7,4,3]、[1,2,2]、[6,0,0]。先看P1,Need [1,2,2] ≤ [3,3,2],满足,P1执行完回收 Allocation [2,0,0],Work 变成 [5,3,2]。再看P2,Need [6,0,0] 不满足;看P0,Need [7,4,3] 也不满足。于是再找——这一轮P2和P0都过不去,说明当前Work下没有可执行进程,当前状态不安全。这就是一个典型的"第一轮能找到、第二轮卡住"的陷阱。

注意:安全性算法里找的是"Need ≤ Work"的进程,方向和大小关系千万别写反,很多人在这里丢分。另外安全序列可能不唯一,题里只要写出一个就行。

3.4 我在PV操作上踩过的三个坑

第一个坑是信号量初值给错。初值代表"一开始有多少个可用资源",互斥信号量永远是1,同步信号量要看题目描述的状态。我曾经把 empty 的初值写成0、full 写成n,结果整道大题的生产者和消费者操作全部反了,后续计算连锁崩盘。现在我养成一个习惯:写完初值先自查一遍——"系统初始时刻,缓冲区是空的、可以放n个",那 empty 就该是n。

第二个坑是P/V顺序颠倒。前面说的"资源信号量先于互斥信号量"这条铁律,我至少栽过两次。后来我在草稿纸上写的时候,会强行按"先资源、后互斥,先V互斥、后V资源"的口诀排一遍,基本不会再错。

第三个坑是忘了互斥保护计数器。读者-写者模型里的 count 是共享变量,多个读者同时进来修改它必须加锁,很多人只记得给写者上 rw 锁,忘了 count 自己的 mutex,导致"两个读者同时判断 count==1"这种经典错误。

4. 内存管理:从地址翻译到页面置换的完整计算链

4.1 地址翻译的统一公式与位运算技巧

分页存储的地址翻译,所有题目都可以用同一套流程解决:

  • 页面大小为 L,逻辑地址为 A;
  • 页号 P = A ÷ L(整除),页内偏移 W = A mod L;
  • 查页表得到物理块号 b;
  • 物理地址 = b × L + W。

关键在于,当 L 是2的整数次幂时,除法取余全部退化成位运算:页号就是地址的高位,偏移就是低 log₂L 位。页面大小4KB,即2¹²,那么偏移占低12位,页号是剩下的高位。

举个具体的例子。32位地址、页面4KB、逻辑地址 0x00002F3A。低12位是偏移,0xF3A = 3898;高20位是页号,0x2 = 2。查页表第2项,假设对应的物理块号是5,物理地址就是 5 × 4096 + 3898 = 20480 + 3898 = 24378,换成十六进制是 0x5F3A。你会发现,物理地址就是把页号部分替换成物理块号,低12位原封不动。

分段存储的逻辑不同:段号加段内偏移,段表里存的是段基址和段长。这里必须做越界检查——偏移量大于段长就产生越界中断。段页式则是先查段表得到页表首址,再查页表得到物理块号,两次查表,访问内存次数增加两次。

4.2 多级页表:页目录项的偏移怎么算

单级页表最大的问题是连续存储:32位地址空间、页面4KB,页表项4B,那页表本身就占 2²⁰ × 4B = 4MB,而且必须连续。多级页表就是为了解决这个问题。

拆位方法很机械。32位地址、页面4KB,偏移占12位,剩下20位是页号。如果用两级页表,每级10位:一级页号(页目录索引)10位,二级页号10位,页内偏移12位。一级页目录有 2¹⁰ = 1024 项,每个二级页表也有1024项,都正好占一页(1024 × 4B = 4KB),完美对齐。

多级页表的核心优势是"按需分配":一级页目录必须常驻,但二级页表只在用到时才创建。一个进程如果只用了很少的虚拟地址空间,二级页表可能只有一两张,占用远小于4MB。同时每个页表刚好一页大小,不存在"必须连续分配大块内存"的问题。

三级、四级页表的拆位方法完全相同,只是把页号位数继续均分。做题时先算总页号位数,再看题目给几级,除一下就是每级位数。这里有个小陷阱:如果页号位数除不尽,多出来的位要放在最靠近页内偏移的那一级(也就是低位的页表级)。这个细节在真题里出现过,按"从低位往高位分"的思路就不会错。

4.3 TLB与有效访问时间

TLB(快表)是页表项的高速缓存。带TLB的访问时间计算有一个基本模型:设TLB访问时间为 t,内存访问时间为 m,TLB命中率为 p。

  • 命中时:访问TLB得到物理块号,再访问一次内存取数据,时间 = t + m。
  • 未命中时:访问TLB(未命中)+ 访问内存中的页表 + 访问内存取数据,时间 = t + m + m = t + 2m。

平均有效访问时间 EAT = p × (t + m) + (1 − p) × (t + 2m)。

如果题目说"TLB访问时间忽略不计",那就直接套 m + (1−p) × m。这里最容易错的是"是否需要额外访问内存查页表"——只有未命中时才需要,命中时不用。我见过不少人把两种情况都算成 t + 2m,结果整题失分。

如果题目里还有缺页的情形,那就再多一层:缺页时需要从磁盘调入页面,时间要加到整个链路上,同时别忘了缺页处理完还要重新执行一次指令。这类题的公式会长一点,但思路一致:把每条路径的概率乘时间加起来。

4.4 页面置换算法与缺页率统计表

页面置换的核心是"物理块不够时淘汰谁"。三种主流算法要能手工推演:

  • OPT(最佳置换):淘汰未来最长时间不再使用的页面。考试里只有它需要看"未来",用来算理论下界。
  • FIFO(先进先出):淘汰在内存中驻留最久的页面。实现简单,但存在 Belady 异常——分配的物理块数增加,缺页次数反而可能上升。这是唯一会有这种异常的算法,是选择题的高频考点。
  • LRU(最近最久未使用):淘汰最长时间未被访问的页面,用栈或者访存时间戳实现,性能接近OPT但开销大。

经典例题:页面访问串为 7,0,1,2,0,3,0,4,2,3,0,3,2,1,2,0,1,7,0,1,物理块数为3。用OPT缺页9次,LRU缺页12次,FIFO缺页15次。这三个数字建议直接记下来,考场上用来校验自己的推演结果——如果你算FIFO只缺了10次,那一定是某一格淘汰对象挑错了。

做这类题我有一个固定的表格模板:横着写访问序列,竖着写物理块的编号,每一格填当前块里的页面号,换页时把被淘汰的页面划掉并标一个记号。必须用笔写,不许在脑子里推,因为一旦超过十步,人脑的短期记忆一定出错。

CLOCK算法和改进型CLOCK(二次机会)的推演规则也比较常考:每个页面配一个访问位,指针顺时针扫描,遇到访问位为1就清零并跳过,遇到0就淘汰。改进型还要看修改位——优先淘汰"访问位0、修改位0"的页面,因为修改过的页面换出时需要写回磁盘,代价更高。

4.5 几个反直觉的结论

虚拟内存这块有几个结论,第一遍学的时候会觉得违反直觉,考试偏偏爱考。

第一,虚拟内存的容量不受物理内存和地址位数限制,而是受CPU寻址范围限制。32位机器的虚拟地址空间上限就是4GB,物理内存装多少都不影响这个上限。

第二,程序不需要全部装入内存就能运行,这是虚拟内存的局部性原理决定的。时间局部性指刚访问过的数据很可能马上再被访问,空间局部性指访问了某个地址,附近的地址很可能被访问。

第三,抖动(颠簸)是"多给点内存"解决不了的。抖动指的是页面频繁换入换出,CPU大量时间花在换页上。根源是多道程序度过高、每个进程分到的物理块太少。解决办法是引入工作集模型,根据程序近期的访问集合动态分配物理块,必要时降低多道程序度。

第四,页表项里同时存了有效位和访问位,有效位标记该页是否在内存中,这直接对应缺页中断的判断。缺页中断属于内中断,且它发生在指令执行过程中,处理完要重新执行该指令——不是从下一条开始。

5. 文件系统与I/O:选择题密度最高、最容易被跳过的一章

5.1 索引结点与文件最大长度的求和套路

这一块是408的高频计算题。题目一般这样给:物理块大小为4KB,每个地址项占4B,索引结点采用混合索引,包含10个直接地址项、1个一级间接、1个二级间接、1个三级间接,求文件最大长度。

第一步先算一个索引块能装多少地址项:4KB ÷ 4B = 1024 项。

然后逐层求和:

层级计算式容量
10个直接地址项10 × 4KB40KB
1个一级间接1024 × 4KB4MB
1个二级间接1024 × 1024 × 4KB4GB
1个三级间接1024³ × 4KB4TB
合计—约 40KB + 4MB + 4GB + 4TB

这套数字几乎每年都会以某种形式出现,记住"4KB、4B、1024、40KB、4MB、4GB、4TB"这条链,考场上现推也就一分钟。

还有一个变体问法:访问文件某个位置的数据,需要读几次磁盘。原则是看这个位置落在哪个区间:落在直接地址范围内,读一次索引结点(如果已在内存则不需要)+ 读一次数据块;落在一级间接范围,需要先读一级索引块,再读数据块。这类题的坑在于"索引结点是否已在内存",题目一般会说明,没说明就按最坏情况算。

5.2 磁盘访问时间与调度算法

磁盘访问时间由三部分组成:

  • 寻道时间:磁头移动到目标磁道所需时间,是最主要的部分。
  • 旋转延迟:目标扇区转到磁头下方所需时间,平均值为半个旋转周期。
  • 传输时间:读写数据本身的时间,通常可以忽略。

转速换算要熟练。7200转/分,一圈用时 60 ÷ 7200 = 8.33ms,平均旋转延迟 = 8.33 ÷ 2 ≈ 4.17ms。如果题目给的是15000转/分,一圈就是4ms,平均旋转延迟2ms。这个换算常年出现在选择题里。

磁盘调度算法和它们的磁头移动总量,用经典例题过一遍最有效。设磁头初始在100号磁道,请求序列为 55, 58, 39, 18, 90, 160, 150, 38, 184。

  • FCFS:按请求先后顺序走,移动量 = 45+3+19+21+72+70+10+112+146 = 498。
  • SSTF(最短寻道优先):100→90→58→55→39→38→18→150→160→184,移动量 = 10+32+3+16+1+20+132+10+24 = 248。
  • SCAN(电梯算法,先向大):100→150→160→184,然后掉头到90→58→55→39→38→18,移动量 = 50+10+24+94+32+3+16+1+20 = 250。
  • CSCAN(循环扫描):100→184 后直接回到最小请求18再往大扫,移动量 = 50+10+24+166+20+1+16+3+32 = 322。

SSTF的移动量最小,但它有"饥饿"问题,热点区域的请求会一直插队。SCAN和CSCAN都避免了饥饿,SCAN的移动量略大于SSTF,CSCAN因为多了"空扫回程"所以更大。做题时一定要先看清磁头当前移动方向,方向反了,整题答案就全错。

5.3 缓冲与I/O控制方式:用一张表解决

I/O控制方式从低级到高级依次是:程序直接控制、中断驱动、DMA、通道。它们解决的核心问题都是"如何减少CPU在I/O上的开销"。

方式数据单位CPU干预频率特点
程序直接控制字(字节)极高,全程轮询CPU与设备串行工作
中断驱动字(字节)高,每字一次中断CPU与设备可并行,但中断频繁
DMA块低,每块一次中断数据直接进内存,不经CPU
通道一组块极低通道是独立处理机,执行通道程序

其中DMA和中断驱动的区别是高频考点:DMA以数据块为单位,中断驱动以字节为单位;DMA在传输过程中不需要CPU干预,只在开始和结束时需要。另外DMA请求的是总线使用权,不经过CPU的地址空间转换,所以不需要保存现场。

缓冲区的计算也是常客。设从磁盘读入一个块到缓冲区的时间为T,从缓冲区送到用户区的时间为M,CPU处理一块数据的时间为C。

  • 单缓冲:每处理一块的平均时间 = max(T, C) + M。因为缓冲区只有一块,输入和传送会互相等待。
  • 双缓冲:每处理一块的平均时间 = max(T, C + M)。两块缓冲区交替使用,读入下一块的同时处理当前块。

判断用哪个公式的窍门是看谁先被卡住:单缓冲时输入和CPU处理争同一块缓冲区,所以先取二者较大者再加传送时间;双缓冲时输入可以和处理并行,所以比的是输入时间和"处理加传送"。

5.4 位示图与空闲空间管理

空闲空间管理有四种方式:空闲表、空闲链表、位示图、成组链接。其中位示图的计算最容易出题。

位示图的规则:每一位对应一个磁盘块,0表示空闲,1表示已分配(具体0/1的含义题目会说明,看反了整题就废了)。给定块号和字长,求它在第几个字的第几位:

  • 字序号(从0开始)= 块号 ÷ 字长,取整数部分;
  • 位序号(从0开始)= 块号 mod 字长。

如果题目要求"字号从1开始编号",那字序号要再加1,位号一般仍从0开始。这个"从0还是从1"的细节每年都有人错,读题时务必圈出来。

反过来也一样常考:已知位示图里第3个字(从1开始编号)的第4位(从0开始编号)被占用,求它对应的块号。这时块号 = (3−1) × 字长 + 4。两个方向都要练熟。

6. 笔记怎么做、错题怎么回填:我的复盘节奏

6.1 概念表和计算表必须分开

我最早的笔记是流水账,概念和公式混在一起,结果复习时要么全看要么全跳。后来我拆成两份:一份是概念表,只放"是什么、为什么、怎么区分"这类文字型知识点,比如"分页和分段的区别""进程和线程的区别""内部碎片和外部碎片的区别",全部整理成三列表格;另一份是计算表,只放公式、符号含义、单位、典型例题的解题步骤。

概念表适合碎片时间翻,吃饭排队的时候看两眼就能记住一组对比;计算表适合坐下来动手推,必须配草稿纸。两者混着看,效率反而低——看文字的时候脑子会自动跳过公式,看公式的时候又不想读定义,最后两边都没吃透。

6.2 错题回填的时机比错题本身更重要

我的错误做法是"当场抄一遍错题",抄完就再也没看过。正确的做法是分两次回填:第一次在当天,只写"错在哪一步",不抄完整题干,目的是趁热定位问题;第二次在一周后,重做一遍这道题,如果还是错,再补一句"为什么会重复错"。第二次回填的那句话往往才是真正的收获。

比如我有一道银行家算法的题错了三次,第三次我才发现问题不在算法本身,而是我在计算 Available 时漏掉了某个进程释放的资源。那之后我给自己加了一条自检规则:每完成一个进程,必须立刻把它的 Allocation 加回 Work,并且把这个动作写在算式旁边。加上这条规则之后,同类题再没错过。

6.3 考前一周只看三样东西

距离考试还有一周的时候,我把复习范围压缩成三样:

第一是所有计算公式的清单。地址翻译、EAT、带权周转、索引结点容量、磁盘移动量、单双缓冲时间、位示图换算,大概十来条,一张A4纸写得下,每天默写一遍。

第二是PV操作的四类模板。默写生产者-消费者和读者-写者的完整代码,检查信号量初值、P/V顺序、计数器加锁这三处。

第三是错题回填的第二句话。那些我自己总结的自检规则,比如"资源信号量先P""索引结点先看是否在内存""磁头方向先确认",一共二十来条,考前一晚扫一遍。

这三样东西加起来不到五页纸,但它们覆盖了我所有丢过分的地方。相比之下,重新翻一遍王道那本厚书反而会制造焦虑——很多内容是选择题的边角料,考前突击性价比极低。

最后分享一个我自己用着很顺手的小习惯:给每道大题标一个"链路名"。比如做完一道地址翻译题,就在旁边写"逻辑地址→拆位→查表→拼物理地址";做完一道页面置换题,就写"访问串→逐格推演→统计缺页"。标完之后再回来复习,看到链路名就能瞬间回忆起整道题的走法,比看题干快得多。操作系统这门课真正难的地方,从来不是知识点多,而是链路长——把每一条链路的名字记住,就等于把整本书压缩成了十几行字。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/30 11:50:39

Linux下安装Redis全攻略:环境准备、编译配置与生产实践

有时候运维工作拼的不是手速,而是规划。以我这些年帮客户搭建缓存服务的经验来看,安装 Redis 本身花的力气只占三成,剩下七成都花在版本选择、环境确认、参数预判这些“看不见的准备工作”上。很多新手上来就下载源码包、解压、make&#xff…

作者头像 李华
网站建设 2026/9/30 11:46:50

OpenClaw接入硅基流动API:Ubuntu服务器部署AI代理全攻略

最近折腾个人AI助手,把OpenClaw接到了硅基流动API上,整体跑通了,顺手记录一下部署和集成的全过程。如果你也准备在Ubuntu服务器上搞一套自己的AI代理,或者正在纠结怎么把大模型API接进现有工具链,这篇内容应该能帮你省…

作者头像 李华
网站建设 2026/9/30 11:46:21

ES搜索实战:从倒排索引原理到Spring Boot集成与性能优化

对于刚接触Elasticsearch(以下简称ES)的人来说,最容易产生的困惑就是:明明照着文档把查询语句写出来了,结果却不尽如人意——要么搜不到想要的文档,要么搜出来一堆不相关的结果。我见过不少项目组把ES当关系…

作者头像 李华
网站建设 2026/9/30 11:45:58

呼叫中心自建全流程拆解:从租赁决策到双机热备避坑指南

简介:一份呼叫中心建设计划书,面向计划从云租赁模式转向自建模式的企业信息化、客服系统规划人员,也适合呼叫中心项目管理与运维团队参考。文档以公司旧有云租赁呼叫中心成本高、客户信息存于第三方机房等痛点为切入点,梳理了采用…

作者头像 李华
网站建设 2026/9/30 11:40:46

iperf网络性能测试实战:从带宽测量到链路质量排查

说实话,网络问题排查是我日常工作中最讨厌的环节之一。上一秒还正常的服务,下一秒用户就反馈“页面打不开”,可你敲 ping 一切正常,看 CPU、内存也没毛病,最后折腾半天才发现问题出在链路质量上。这种时候,…

作者头像 李华