很多考系统架构师的同行,复习到“操作系统知识”这一章的时候,最容易卡壳的往往不是进程管理,而是存储管理和设备管理这两块。原因其实很简单:一是概念抽象,逻辑地址、物理地址、页表、快表、DMA、通道、SPOOLing,名词堆在一起,不彻底理解就成了一团浆糊;二是这部分特别喜欢出小计算,页表换算、缺页次数、磁盘寻道长度,算错一步整道题就白给;三是案例分析题里经常拿存储瓶颈、I/O瓶颈做素材,光背概念根本答不到得分点上。
我备考那年在这两块上反复折腾过,后来把教材重新拆了一遍,按“这东西到底解决什么问题”的思路重新整理了一份笔记,再回去做历年真题,正确率明显不一样。这篇就把我梳理出来的框架和实战心得写出来,适合正在备考系统架构师、或者想系统过一遍操作系统存储与设备管理部分的同行参考。内容不需要你一下子全记住,但跟着走一遍,至少能把这些考点串成一条线。
1. 存储管理到底在管什么:从地址转换看操作系统的基本盘
开始抠细节之前,先把存储管理的目标想清楚。操作系统管内存,本质上就三件事:第一,多个进程怎么把有限的内存分着用,而且互相不干扰;第二,程序员写的程序用的是逻辑地址,硬件需要物理地址,两者怎么对上;第三,内存不够用的时候,用什么样的策略来换入换出。这三件事,就是存储管理的全部。
1.1 逻辑地址和物理地址:程序员看到的世界和硬件运行的世界
先解决一个最容易混淆的概念。一个C程序里声明数组后,你通过下标去访问元素,这个下标在编译链接阶段形成的是逻辑地址。逻辑地址是相对于程序自身的,它描述的是“这个变量在我这个程序空间里的哪个位置”,而不是它在内存条上真正待的位置。物理地址则是内存单元的真实编号,是内存硬件能直接认识的地址。
举个生活化的例子:逻辑地址相当于你手绘的办公室分布图上标的“3号工位”,物理地址相当于工位上贴的固定资产编号。外人来找你,只看工位图是找不到的,必须有一张“3号工位对应资产编号XX-XX-XX”的对照表,这张对照表就是地址映射的核心。
把逻辑地址转成物理地址的过程,叫重定位。重定位有静态和动态两种:
- 静态重定位:程序加载到内存时,由装载器一次性把所有指令里的地址都改成物理地址。优点是简单,缺点是程序一旦装入内存就不能再移动了,想换出换入也很麻烦,因为物理地址已经写死到指令里了。
- 动态重定位:程序加载时不改指令里的逻辑地址,运行时每次访问内存,由硬件(基址寄存器+地址加法器)在瞬间做一次“逻辑地址+基址”的换算。现代操作系统基本都是动态重定位,原因很简单:程序可以在内存里移动,可以先换出再换入,配合虚拟存储做灵活调度。
理解这个区别很重要。后面讲分页、分段、虚拟存储,本质上都是在解决“逻辑地址和物理地址怎么快速可靠地对应起来”这一件事,只是做法越来越精巧。
1.2 连续分配和内存碎片:固定分区、动态分区与紧凑
最原始的存储管理方式是连续分配,也就是给每个进程一块连续的内存区域。连续分配又分两代:
- 固定分区:系统启动时把内存切成若干固定大小的小块,每个分区装一个进程。优点是简单,缺点是分区大小很难定:定小了,大进程装不下;定大了,小进程用不满,小块里浪费的空间就是内部碎片。考试里选择题经常让你判断“内部碎片和外部碎片分别出现在哪种分配方式”,固定分区对应内部碎片。
- 动态分区:进程来多少就给多少,按需切割内存。这种方案没有内部碎片,但频繁加载、卸载进程后,内存里会出现很多零散的小空洞,每个洞都小到装不下新进程,加起来却不少,这叫外部碎片。
为了解决外部碎片,就有了紧凑技术:把内存里所有进程往一端搬移,把分散的空洞合并成一个大空闲区。代价是搬移过程要占用CPU时间,进程也不能运行,所以频繁紧凑并不划算。考试如果问你“紧凑技术到底解决的是内部碎片还是外部碎片”,答案是外部碎片,这里容易踩坑。
动态分区还有一个考点,就是空闲分区分配算法,常见的有三种:
| 算法 | 策略 | 优点 | 缺点 |
|---|---|---|---|
| 首次适应(FF) | 从低地址开始找第一个能装下的分区 | 实现简单,分配快 | 低地址容易形成大量小碎片 |
| 最佳适应(BF) | 找所有能装下分区里最小的那个 | 尽量保留大分区 | 碎片更琐碎,查找慢 |
| 最坏适应(WF) | 找最大的那个分区切 | 剩余分区不会太小 | 大分区被快速切没,对大进程不友好 |
实际系统中首次适应和最佳适应都比较常见,最坏适应用得少。选择题里如果问“哪种算法最容易产生大量难以利用的小碎片”,多数情况指的是最佳适应,因为它是“按需精切”,切到最后全是边角料。
1.3 覆盖与交换:给内存扩容的两种土办法
在虚拟存储技术成熟之前,人们想了两招让程序能突破物理内存上限。
覆盖的思路是:一个程序没必要把全部代码和数据同时留在内存里。比如一个程序有主模块、模块A和模块B,A和B不会同时执行,那就可以让A和B共享同一块内存区域。放在谁身上用呢?开发者在编程阶段就要手工划分覆盖结构,所以覆盖是“程序员的活”,操作系统只提供支持。这个知识点现在考得不多,但偶有选择题会问“覆盖技术要求程序员提供覆盖结构”,要能识别。
交换的思路更宏观:以进程为单位,把整个进程从内存换到磁盘的交换区,把另一个进程从磁盘换入内存。它的意义在于,多道程序的并发度不用再受物理内存总容量的限制。但交换有几个代价:一是换出时进程状态要完整保存,换入后要能恢复;二是进程换入换出时不能执行,调度器要把它挂起;三是交换区大小和换出时机的选择有讲究。理解交换之后,再去看虚拟存储里的请求分页,会发现思路是一脉相承的——只不过交换换整个进程,分页换的是页面。
2. 分页分段与地址换算:一张页表看穿考试的底层逻辑
连续分配的碎片问题让人意识到,能不能不要求进程“整块连续”?分页存储管理就是在这种背景下出现的。它把物理内存切成等大的页框,把进程的逻辑空间切成同样大小的页面。一个进程的页面可以不连续地散落在各个页框中,只要有一张页表维护映射关系就行了。
2.1 分页存储管理:物理内存按框切,逻辑空间按页切
分页的思路相当于把一个大蛋糕先切成固定大小的方块,进程需要吃几块就拿几块,不需要一整块完整蛋糕。页面大小一般是2的整数次幂,比如4KB。为什么必须是2的幂?因为这样地址转换可以用位运算快速完成——逻辑地址的低位直接就是页内偏移,高位是页号,不需要除法。别小看这个设计,它直接影响地址转换的速度,而地址转换是每条指令访问内存都会涉及的,慢一点都不行。
页表就是一张“页号 → 页框号”的映射表。硬件访问一个逻辑地址时,先查页表拿到页框号,再拼接页内偏移,合成物理地址。这张表存在哪?存在内存里。这样一来,每条访存指令要多访问一次内存去查页表,性能损失接近一半,所以硬件引入了快表(TLB,Translation Lookaside Buffer),把最近访问过的“页号→页框号”缓存到CPU的快速存储里。TLB命中率直接决定存储系统的性能,这也是案例题里常常提到的优化点。
2.2 地址转换实操:一道十六进制换算题讲透
很多人在页表换算题上丢分,不是因为不懂原理,而是十六进制和二进制转换不够熟。我拿一道典型例题演示完整过程:
假设页面大小为4KB,某进程的逻辑地址为0x3A25,当前页表映射关系为:0号页→2号页框,1号页→5号页框,2号页→8号页框,3号页→7号页框。求对应的物理地址。
第一步,确定页内偏移位数。4KB等于2的12次方,所以逻辑地址低12位是页内偏移,高4位是页号。
第二步,把0x3A25拆开。0x3A25用二进制表示是0011 1010 0010 0101,其中高4位0011就是页号3,低12位1010 0010 0101是页内偏移,也就是十六进制的0xA25。
第三步,查页表,3号页对应7号页框。
第四步,拼物理地址。因为页面大小是2的幂,所以不用做乘法,直接把页框号7和页内偏移0xA25拼接起来,物理地址就是0x7A25。
如果是非2的幂的分区式内存,那就得老老实实用“基址+偏移”计算。这里要注意分页和分段的区别:分页的页面大小固定且为2的幂,所以能拼接;分段的段长是可变的,不能简单拼接,必须用段基址加上段内偏移。
考试里还可能问你“逻辑地址0x3A25的页号是几、页内偏移是几”或者“访问该地址需要查几次页表”。后者在多级页表场景下有标准答案:N级页表需要N+1次访存(N次查表加1次真正取数据),但有了快表后,命中时只需要1次。
2.3 分段存储管理:按用户视角的逻辑模块划分
分页是物理视角的方案,它压根不管程序的结构,只是机械地把逻辑空间切成等大的页。但程序员写代码时,是一个模块一个模块组织的:代码段、数据段、栈段、堆段,每个段的逻辑功能不同,需要的保护属性也不同(代码段只读,数据段可读写)。分段存储管理正是按这种用户视角来划分内存的。
段的长度不再是固定大小,而是由逻辑结构决定,这带来了几个特性:
- 便于共享:两个进程想共享一个库,只要让各自的段表项指向同一个段,不用像分页那样按页粒度的共享那么麻烦。
- 便于保护:段表项里可以标记读写权限,访问越权时会触发保护异常。
- 段长可变,所以地址转换是“段号→段基址+段长”的映射,不能直接拼接页内偏移。
分页没有外部碎片但有内部碎片;分段没有内部碎片但有外部碎片——因为段长可变,进程装载和释放后内存里会留下碎片。这个概念考得非常多,建议用对比表反复看几遍:
| 维度 | 分页 | 分段 | 段页式 |
|---|---|---|---|
| 地址结构 | 页号+页内偏移 | 段号+段内偏移 | 段号+页号+页内偏移 |
| 页面/段长 | 固定,2的幂 | 可变 | 段可变,段内页面固定 |
| 是否对用户透明 | 透明,用户无感知 | 可见,按逻辑模块划分 | 系统级结合两者 |
| 外部碎片 | 无 | 有 | 无 |
| 内部碎片 | 有 | 无 | 有 |
| 便于共享和保护 | 较麻烦 | 方便 | 兼顾 |
段页式是两者的结合:逻辑地址先按分段结构分成“段号+段内逻辑地址”,段内逻辑地址再按分页机制进一步划分成“页号+页内偏移”。访问时要先查段表、再查页表,两次内存访问加上一次真正的数据访问,等于三次访存,所以同样依赖快表来加速。系统架构师考试对这个点的考查频率很高,特别是“段页式访问一个数据需要几次访存”这类题目,答案要能脱口而出。
3. 虚拟存储与页面置换:抖动的本质是对局部性的背叛
分页和分段解决了内存利用率问题,但还没解决“程序比内存还大怎么办”的问题。虚拟存储的答案是:别把整个程序都装进内存,让CPU只加载当前正在用的那部分,其余留在磁盘上,用的时候再按需调入。
3.1 虚拟内存的底气:局部性原理
虚拟存储能成立,靠的是局部性原理。这个原理说人话就是:程序在一小段时间里,访问的指令和数据都集中在某个局部区域。一个循环会被反复执行,循环体里的指令自然反复用到,这是时间局部性;一个数组会按顺序连续访问,相邻地址的数据被一起取进来,这是空间局部性。
局部性原理的意义在于:既然进程当前用到的页面只占整体的一小部分,那么只要把这部分放进内存,进程就能正常运行。当某条指令要访问的页面不在内存时,硬件触发缺页中断,操作系统从磁盘把页面读入内存,然后重新执行这条指令。这个“按需调页”的机制,就是请求分页虚拟存储的核心。
这里要纠正一个认知误区:虚拟存储不是把你的物理内存变大了,而是它替你管理了“磁盘充当内存”这件事。物理内存装不下时,进程照样能跑,只是速度会大打折扣。
3.2 OPT、FIFO、LRU、Clock:四个算法的本质差异
页面需要换出时,选哪个页面滚蛋,就是页面置换算法的事。学校教材和软考大纲里,四个算法必须彻底搞清楚:
- OPT(最佳置换算法):选择未来最长时间不会被访问的页面换出。它缺页率理论上最低,但未来不可预知,所以只能作为衡量其他算法优劣的基准。真题里如果给出未来页面走向让你算OPT的缺页次数,那直接按定义数就行。
- FIFO(先进先出):换出最早进入内存的页面。实现最简单,用一个队列就行。但它可能出现Belady异常——增加分配给进程的页框数,缺页次数反而增加了。这个反直觉现象是高频考点。
- LRU(最近最久未使用):换出最长时间没被访问的页面。它利用局部性原理,认为最近没用的将来大概率也不用。性能好,但要在访问时维护“最近使用时间”,硬件开销大。
- Clock(时钟置换算法):也叫二次机会算法,是LRU的一种近似实现。每个页面有一个使用位,页面被访问时置1;需要淘汰时,像时钟指针一样循环扫描,遇到使用位为1就改成0并跳过,遇到0就淘汰。它用很小的代价换取了接近LRU的效果。操作系统教材里的改进型Clock还考虑了修改位,优先淘汰没被修改过的干净页面,因为脏页面换出前需要写回磁盘,代价更大。
考选择题时,最常出现的坑是“LRU必须基于过去的信息,OPT必须基于未来的信息”,两者不要搞混。
3.3 手算缺页次数:不要偷懒,算一遍就记住了
前面说的都是概念,这里我建议你跟着我算一遍。给定页面走向:1, 2, 3, 4, 1, 2, 5, 1, 2, 3, 4, 5,分配给进程的页框数为3,分别求FIFO和LRU的缺页次数。
FIFO的推演过程,我直接在表里标出来:
| 页面走向 | 1 | 2 | 3 | 4 | 1 | 2 | 5 | 1 | 2 | 3 | 4 | 5 |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 页框状态 | 1 | 1,2 | 1,2,3 | 2,3,4 | 3,4,1 | 4,1,2 | 1,2,5 | 1,2,5 | 1,2,5 | 2,5,3 | 5,3,4 | 3,4,5 |
| 是否缺页 | × | × | × | × | × | × | × | √ | √ | × | × | × |
FIFO一共缺页10次。注意第8位和第9位的1、2是命中的,因为5换入时淘汰的是4,1和2还在页框里。
LRU的推演是另一个故事:访问4时淘汰1,访问1时淘汰2,访问2时淘汰3,访问5时淘汰4,访问3时淘汰5,访问4时淘汰1,访问5时淘汰2,最终也是缺页10次。这个例子里两种算法缺页次数恰好一样,但淘汰的选择完全不同。很多同学在这里产生疑惑,觉得LRU不是更优吗?对一个具体序列,LRU并不总是优于FIFO,只是总体上通常更好;真正关键的区别是FIFO有Belady异常,LRU没有。
我个人的刷题经验是:置换算法一定别只背结论,拿出一张草稿纸,把页框一行一行推过去,推完一个序列,所有细节都记住了。网上那些“FIFO缺页9次”的说法,多半是因为把命中页面挪到队尾或者没遵守淘汰顺序算错了。
3.4 工作集与抖动:为什么越换越慢
页面置换算法解决的是“换谁出去”,而工作集理论回答的是“到底应该给进程多少页框才够用”。所谓工作集,是进程在一段时间窗口内实际访问的页面集合。如果操作系统分给进程的页框数小于它的工作集大小,进程就会频繁缺页,CPU大部分时间都在等磁盘I/O,系统吞吐量断崖式下跌,这就是抖动。
抖动的本质是“并发度过高导致每个进程的内存都不够用”。处理抖动的常用策略有:
- 采用局部置换策略,让一个进程的缺页只影响它自己,不让别的进程遭殃。
- 挂起部分进程,把它们的页面抢过来分配给正在运行的进程,等系统压力小了再恢复。
- 控制多道程序度,不让同时运行的进程数量超过内存能承受的极限。
系统架构师案例题里,如果给你一个数据库服务器的内存配置,让你分析为什么数据库突然变慢,很大概率就落在“内存分配不合理导致缺页率上升”这个套路上。答题时把工作集和抖动的逻辑链写清楚,比堆一堆监控数据管用得多。
4. 设备管理的本质:I/O 控制演进、缓冲与 SPOOLing
存储管理管的是内存,设备管理管的是外设和I/O系统。外设种类多、速度差异大、工作方式完全不同,所以设备管理的第一件事就是分类。
4.1 设备分类和目标:为什么有的设备叫块,有的叫字符
设备大体有两种分类维度:
按信息交换单位分:块设备以数据块为单位读写,比如磁盘、SSD,可以随机访问,传输速度相对快;字符设备以字符为单位读写,比如键盘、串口,只能顺序访问,速度差异很大。
按资源性质分:独占设备一次只能给一个进程用,比如打印机、磁带机;共享设备允许多个进程交替使用,比如磁盘;虚拟设备是通过软件技术把独占设备改造成可共享的逻辑设备,最有名的例子就是用SPOOLing技术改造打印机。
设备管理要干的事也就清晰了:一是为进程分配设备,避免争抢冲突;二是控制设备完成数据传输;三是提供设备独立性,让用户用逻辑设备名访问,不必关心底层物理设备的具体型号;四是应对设备故障和异常。
4.2 I/O控制方式的四层演进
设备管理最核心的考点是I/O控制方式的演进,这个脉络其实非常清晰:
第一层,程序查询方式。CPU不断轮询设备状态寄存器,直到设备准备好才传输数据。整个过程CPU都在忙等,效率极其低下,但实现最简单。可以用“排队打饭时一直盯着阿姨有没有抬头”来理解。
第二层,中断驱动方式。CPU发出I/O命令后,不再空转,而是去执行其他任务,设备完成操作后通过中断通知CPU。这一下把CPU从等待中解放出来。但问题还在:每次传输一个字或一个字节都要触发一次中断,中断次数太多,CPU大量时间花在中断处理上。
第三层,DMA(直接存储器访问)方式。DMA控制器接管数据搬运工作,CPU只需要设置好源地址、目的地址和传输长度,然后就可以去干别的。数据块传完后DMA发一次中断通知CPU。这就相当于你雇了一个跑腿小哥,让他一次帮你把一箱文件搬到隔壁楼,搬完给你打个电话,你不需要一页一页自己跑。
第四层,通道方式。通道是独立的I/O处理器,有自己的指令系统,可以执行通道程序,控制多台设备的复杂I/O过程。CPU只需发起一个I/O指令,后面的整套操作由通道自主完成。这相当于你给跑腿公司下单,公司自己派人、自己规划路线、自己交货,你只管最后验收。
这四层的演进关系,每一年考试几乎都会碰到,核心逻辑是“CPU参与程度越来越低,设备智能程度越来越高”。
4.3 缓冲技术:解决速度不匹配与数据黏滞
CPU和打印机速度相差几个数量级,如果CPU直接把数据一条条送给打印机,那CPU基本就瘫痪了。缓冲技术的用途就在这里:在内存里划出一块区域,暂时存放数据,让速度不匹配的双方向通过缓冲区交换数据。
单缓冲是设备先把数据送入缓冲区,CPU再取走处理,两者的操作串行。双缓冲则可以让设备填满第一个缓冲区的同时,CPU处理第二个缓冲区,交替进行,实现一定程度的并行。如果题目问双缓冲对某个工作的平均处理时间,可以套公式:每块处理时间≈max(CPU处理时间, I/O传输时间)+直接存储器访问开销。循环缓冲和缓冲池则是更通用的扩展,多个缓冲区首尾相连或组成池子,供不同设备共享。
这块考得不算深,但“为什么引入双缓冲”“单缓冲和双缓冲在生产率计算上的区别”是常见选择题,建议把两道典型的生产者消费者算例做一遍,比单纯背概念强。
4.4 SPOOLing与虚拟设备:把独占设备变成可共享的设备
SPOOLing可能是设备管理里最贴近实战的考点,因为它体现了“用软件改造硬件资源”的典型思路。
SPOOLing的核心构成有四部分:输入井和输出井,它们都建立在磁盘上,用来暂存数据;输入缓冲区和输出缓冲区,位于内存;输入进程和输出进程,负责模拟外围设备。以打印任务为例,多个进程同时请求打印时,各自的输出内容先被写入磁盘上的输出井,形成打印队列,输出进程按队列顺序把数据发送给打印机。每个进程看起来都觉得自己独占了一台打印机,但实际上打印机是被多个进程轮流使用的。
这个机制的价值不必多说,它解决了独占设备利用率低的问题,还间接缓解了“进程持有打印机等另一个设备”导致的死锁风险。考试如果问你“SPOOLing离不开哪两种硬件的配合”,答案是磁盘和内存;如果问你“SPOOLing技术把独占设备变成了什么设备”,答案是虚拟设备,也有人叫逻辑设备,这两个说法都对。
设备分配与死锁的关系也是容易混淆的点:安全分配方式,进程发出I/O请求后进入阻塞态,直到I/O完成才唤醒,相当于“持有不再等待”,不会死锁,但设备利用率低;不安全分配方式,进程可以继续运行等待设备,设备利用率高,但可能造成“拿着A设备等B设备”的循环等待。选择题问你“哪种分配方式可能导致死锁”,答案是不安全分配。
5. 磁盘调度与存储可靠性:案例分析里最常被当作素材的考点
设备管理里性价比最低、最容易被临时抱佛脚的,是磁盘这块。它出现率不低,而且不管选择题还是案例题都能拿来出题,所以有必要系统梳理。
5.1 磁盘的读写模型:寻道延迟、旋转延迟、传输时间
一次磁盘读写,花的时间由三块组成:寻道时间(磁头移动到目标磁道)、旋转延迟(盘片转到目标扇区)、传输时间(读写数据本身)。旋转延迟的平均值怎么算?如果磁盘转速是7200转/分,那么转一圈的时间是60/7200秒,也就是8.33毫秒,平均旋转延迟取半圈,约4.17毫秒。
这类题在软考里出现过不止一次:给你转速和平均寻道时间,让你算平均访问时间,你只要把平均寻道时间加上平均旋转延迟,再加上传输时间(通常题目会给一个很小的固定值),就能拿到分。传输时间一般很小,很多时候甚至可以忽略,但题目明确给了就一定要加进去。
5.2 磁盘调度算法:从FCFS到CSCAN
磁盘调度算法的目标很朴素:减少磁头移动的总距离,从而降低平均等待时间。考试常考五个算法:
- FCFS(先来先服务):按请求到达顺序处理,公平但没有优化,可能让磁头在磁盘上乱跑。
- SSTF(最短寻道时间优先):每次处理离当前磁道最近的请求。平均寻道距离短,但可能出现“饥饿”——远处的请求一直等不到服务。
- SCAN(电梯算法):磁头先朝一个方向移动,沿途处理请求,走到头再反向,像电梯上下楼。这个算法不会饥饿,但“走到头”这一要求有点机械。
- C-SCAN(循环扫描):单向服务,磁盘头从一端走到另一端,处理途中请求,然后立刻跳回起点。对每个磁道的等待时间更均匀。
- LOOK和C-LOOK:SCAN和C-SCAN的优化版,磁头只移动到最远的请求位置就回头,不用真的走到磁盘端点。
我拿一个经典算例演示计算。假设当前磁头位于53号磁道,请求队列是98、183、37、122、14、124、65、67,磁头向磁道号增大的方向移动。SSTF的服务顺序是:53→65→67→37→14→98→122→124→183,移动总量为12+2+30+23+84+24+2+59=236。SCAN的服务顺序是:53→65→67→98→122→124→183,然后回头→37→14,移动总量为12+2+31+24+2+59+146+23=299。
这类计算题没什么难度,但特别考验细心。我给你的建议是:先列一个“当前磁道→下一个服务磁道”的表格,再算每一段的差值,最后求和,步骤写清楚,千万别用嘴算跳步。选择题里陷阱基本都出在“方向搞反了”或者“SSTF不是贪心到最小值,而是每一步贪心”。
5.3 RAID级别:软考反复出现但总是记混的一张表
RAID算不算设备管理?严格说它是存储系统层面的技术,但系统架构师考试里,它一般出现在存储相关的选题或案例里,和磁盘知识同时出现。RAID的核心思想是把多块物理磁盘组合成一个逻辑存储池,通过冗余或条带化提升性能或可靠性。
历年常考的就四个级别,用一张表就能理清:
| RAID级别 | 最少磁盘数 | 容错能力 | 空间利用率 | 特点 | 典型场景 |
|---|---|---|---|---|---|
| RAID 0 | 2 | 无 | 100% | 条带化,读写性能高 | 临时数据、高速缓存 |
| RAID 1 | 2 | 允许坏1块 | 50% | 镜像,写性能略降 | 系统盘、关键日志 |
| RAID 5 | 3 | 允许坏1块 | (n-1)/n | 分布式奇偶校验 | 文件服务器、通用存储 |
| RAID 10 | 4 | 每个镜像对允许坏1块 | 50% | 先镜像后条带 | 核心数据库 |
选择题最喜欢的问法:RAID 5至少需要几块盘,坏了能容忍几块;RAID 0和RAID 1哪个有冗余;空间利用率差多少。这类题只要把上面的表刻进脑子里,基本不丢分。还有一个容易迷惑的点:RAID 10和RAID 01的区别,前者是先镜像再条带,后者是先条带再镜像,从可靠性角度RAID 10明显更优,因为RAID 01里一个镜像对坏掉一块盘,整个条带组就废了。
6. 这套知识怎么变成应试分:题型分布、做题顺序和易错点
最后把前面所有内容落到“拿分”这件事上。我问过不少一起备考的同行,发现大家共同的困惑是:知道概念,但题目换个问法就认不出来了。这里面有规律可循。
6.1 选择题里反复出现的三个挖坑点
第一个坑是逻辑地址和物理地址的概念偷换。题目说“程序员看到的是物理地址”或者“链接后生成的是物理地址”,都是错的。编译链接生成的是逻辑地址,加载或运行时才变成物理地址。
第二个坑是页面置换的Belady异常。题目问“哪种置换算法可能出现进程分配的页框数增加,缺页率反而升高”,你得立刻反应是FIFO。如果问“哪种算法不可能出现”,答案通常是LRU——因为LRU属于栈式算法,页框增加时缺页数只会减少或保持不变。
第三个坑是通道和DMA的区别。DMA一次传输仍需要CPU设置参数、收到一个中断;通道可以执行通道程序,管理多台设备,处理更复杂的I/O过程。选项里如果说DMA可以执行通道程序,那就是错的。
6.2 案例题里的结合点:存储瓶颈和I/O瓶颈
案例分析题不会只考“页面置换算法选哪个”,它喜欢把存储管理、设备管理嵌在一个真实场景里。举几个常见套路:
- 给一个进程的虚拟内存配置和缺页率监控数据,让你分析系统变慢的原因。这时你要答出:内存分配不足→驻留集小于工作集→缺页频繁→CPU等待I/O→吞吐量下降,并给出增加内存、调大工作集窗口或减少并发进程数的应对方案。
- 给一个数据库服务器的存储架构,涉及RAID级别选择。你要能从可靠性和性能两个维度分析为什么选RAID 10而不是RAID 5。这里的核心论据是:数据库读多写少,但写请求对性能极度敏感,RAID 10写操作不需要计算校验值,所以延迟更稳定。
- 给一个I/O密集型系统的设备配置,让你指出瓶颈。答题思路基本是:先看CPU参与I/O的程度,再看缓冲是否足够,再看磁盘调度策略是否合理,最后看是否有设备分配导致的资源等待。
我复习时有个习惯:每做一道案例题,先用一句话写出“出题人到底想考哪个知识点”,再去对答案。这个方法帮我避免了大量“读题都懂,写答案就跑偏”的情况。
6.3 梳理体系比刷题更重要:一条线串起所有考点
如果你时间紧张,我建议你放下题海,先按这条线把知识点串一遍:程序编译出逻辑地址,动态重定位把逻辑地址映射到物理地址;连续分配有碎片,所以有了分页、分段;单级页表开销大,所以有多级页表和快表;内存不够用,所以有虚拟存储和页面置换;外设速度慢、种类杂,所以有I/O控制方式演进、缓冲技术、SPOOLing和磁盘调度。每一环都是在解决前一个方案留下的问题,这样前后是连得上的,而不是散落的记忆点。
我做真题的时候发现,近五年的选择题里,存储和设备的题目占比基本稳定,页表换算、页面置换、磁盘调度这三类计算题几乎年年都有。这三类题不偏不怪,只要按前面3.3节和5.2节的方法亲手算过一遍,考场上是实打实的送分题。
最后说点个人体会:存储管理和设备管理这两章,很多内容乍看和工作关系不大,但设计一个系统、排查一个线上故障时,你迟早会在内存占用和I/O等待上跟它们打照面。当时我啃这些知识点纯粹为了应付考试,后来做架构评审时才发现,那些关于内存换页、I/O调度、RAID选择的判断,全都在这里打过底。备考的过程虽然枯燥,但这些底层知识带来的回报,往往比我预想的更持久。