简介:这是一份面向计算机专业本科生的操作系统课程期末复习笔记,聚焦核心概念梳理与考点精讲,帮助学生高效应对期末考试。笔记系统覆盖操作系统目标(方便性、有效性、可扩充性、开放性)、发展历程(人工操作→批处理→分时→实时系统)、四大基本特性(并发性、共享性、虚拟性、异步性),以及处理机、存储器、设备和文件四大管理功能;重点详解进程状态转换、PCB结构、进程同步机制(信号量P/V操作、整型/记录型/AND型/信号量集)、前趋图、临界区、管程及经典同步问题。资源为单个1.17MB的Word文档(.docx),内容排版清晰、术语准确、逻辑连贯,便于打印背诵与碎片化复习。目前已有779人学习下载,适合作为教材补充、课堂笔记对照与考前冲刺提纲使用。
1. 操作系统期末复习笔记:不是“背概念清单”,而是帮你把散落的齿轮拧成一台能转的机器
你有没有过这种感觉:翻开操作系统课本,满页都是“并发”“临界区”“快表”“松弛度”……每个词单独看都像认识,合在一起却像一盒被摇散的齿轮——知道它们本该咬合转动,但就是找不到哪颗该卡在哪条齿槽里?期末前熬夜抄笔记,结果考场上看到“请用信号量实现哲学家进餐问题”,脑子瞬间空白:mutex 是放筷子前还是放筷子后?Swait 的参数顺序到底怎么排?为什么银行家算法算出“安全序列”就等于不会死锁?
这本《操作系统期末复习笔记》要解决的,根本不是“多记一个定义”,而是帮你重建一套可运转的认知框架:它把操作系统还原成一个真实在跑的系统——CPU 是工人,内存是车间,进程是流水线上的工单,信号量是车间门口的取号机,死锁是两组工人同时攥着对方的工具不撒手……所有术语,都回归到“谁在什么时候、为什么、要做什么事”这个动作链条里。它不教你“标准答案”,而是给你一把螺丝刀:当你面对一道新题,能自己拆开、看清零件关系、再拧紧。这不是速成口诀,而是一张让你期末不靠玄学、只靠逻辑就能推导出解法的路线图。
2. 操作系统到底是什么:不是软件,而是计算机世界的“交通管制中心”
2.1 它存在的根本理由:人和机器之间,横亘着一道“理解鸿沟”
想象你让一个完全没学过编程的人,直接对着 CPU 的二进制指令(比如10110000 01100001)写程序——这就像让一个只会说中文的人,用摩斯电码给纽约交易所下单。操作系统,就是那个把“我要打印这份报告”翻译成 CPU 能听懂的、精确到每一个电压脉冲的指令集,并确保打印机、内存、硬盘这些硬件像一支训练有素的仪仗队一样同步行动的“超级翻译官+总调度员”。
提示:注意“翻译”只是起点。真正的难点在于“协调”——当 10 个程序同时喊“我要用打印机!”,操作系统得决定谁先打、谁等会儿、谁的纸卡住了不能影响别人。这比单纯翻译难十倍。
2.2 四大核心特性:不是抽象名词,而是系统必须具备的“生存本能”
并发(Concurrency):不是“同时干”,而是“轮流抢时间片”。
打个比方:你手机上微信视频、网易云听歌、后台微信消息提醒同时在动,但 CPU 实际上一秒内切了上千次任务——就像一个厨师(CPU)在三个灶台(微信、音乐、消息)间疯狂颠勺,每锅只炒 0.001 秒,人眼看着是“三锅齐爆”,其实是“微观串行,宏观并行”。没有并发,你的手机点开第二个 App 就得等第一个彻底关掉。共享(Sharing):资源不是“租给谁就归谁”,而是“大家共用,但得守规矩”。
比如打印机:A 同学发了打印请求,B 同学也发了,操作系统不会让两人文件混成一团吐出来。它用“互斥锁”(比如 mutex 信号量)保证:A 打印时,B 的请求在队列里排队;A 打完,锁自动释放,B 才能进。这叫互斥共享。而内存里的数据,多个进程可以同时读(不改),这就叫同时访问共享——共享不是一刀切,而是分场景定规则。虚拟(Virtualization):把“一个真家伙”,变成“多个假分身”。
你电脑只有 16GB 物理内存,但能同时开 Chrome(占 3GB)、PyCharm(占 2GB)、游戏(占 6GB)……加起来远超 16GB?操作系统在“骗人”:它把硬盘划出一块区域当“虚拟内存”,把暂时不用的 Chrome 页面数据悄悄挪过去腾地方,需要时再闪电般换回来。对你来说,仿佛有无限内存——这就是虚拟存储器。同理,一个物理 CPU,通过分时技术,让每个进程都觉得自己独占一个“专属 CPU”。异步(Asynchrony):进程不是匀速前进的赛车,而是随时可能“踩刹车”的公交车。
一个程序运行中突然要读硬盘(慢!),CPU 就不会傻等,立刻切走干别的活;等硬盘数据终于到了,操作系统再把它唤醒。所以进程执行是“走两步、停三秒、再走五步”,速度不可预测。操作系统必须设计成能容忍这种“断断续续”,否则整个系统就卡死了。
2.3 为什么“方便性”和“有效性”是最高目标?
课本说“方便性是让计算机易学易用”,但这太轻了。真正关键的是:它把硬件的残酷复杂性,对用户彻底隐藏。
你双击一个.exe文件,背后发生了什么?
→ 操作系统检查磁盘找到文件 → 把代码从硬盘读进内存 → 分配内存空间 → 创建新进程(填 PCB)→ 给它分配 CPU 时间片 → 监控它别越界乱改其他程序内存 → 如果它崩溃,优雅终止而不拖垮整个系统……
这一连串动作,用户零感知。这就是“方便性”的重量——它不是锦上添花,而是让计算机从“工程师玩具”变成“全民工具”的基石。
而“有效性”直指命门:CPU 别闲着,内存别空着,硬盘别傻等。
多道批处理系统为什么比单道强?因为单道时,CPU 等着打印机吐字,全程发呆;多道系统则趁这空档,立刻拉另一个程序进来算数——CPU 利用率从 30% 拉到 85%。分时系统为什么让用户觉得“响应快”?因为它把 CPU 时间切成 10ms 一片,100 个用户每人轮一圈,你敲回车,0.1 秒内必有反馈。没有有效性,再方便的界面也是幻觉。
3. 进程:操作系统管理任务的“最小身份证”,不是程序本身
3.1 程序 vs 进程:静态图纸 vs 动态施工队
- 程序(Program):是存放在硬盘上的、一动不动的代码和数据集合,就像一份建筑蓝图。它不占内存,不消耗 CPU,只是个文件。
- 进程(Process):是程序的一次动态执行过程,是操作系统真正调度和管理的对象。它像一支接到蓝图后进场施工的工程队——有自己的工人(线程)、工具(内存空间)、进度表(PCB)、甚至临时仓库(栈和堆)。同一份蓝图(程序),可以同时有 3 支施工队(3 个进程)在不同工地(不同数据)上干活。
注意:进程是“活”的。它有生命周期:创建(
fork())→ 就绪(排队等 CPU)→ 运行(CPU 正在执行它)→ 阻塞(等键盘输入/硬盘读取)→ 终止(exit())。这个状态流转,全靠操作系统内核控制。
3.2 进程控制块(PCB):进程的“电子档案袋”,操作系统靠它认人
你去政府办事,窗口不看你本人,只查你的身份证(PCB)。PCB 是操作系统为每个进程创建的唯一数据结构,里面装着它的全部“身份信息”:
// 简化版 PCB 结构示意(非真实代码,重在理解) struct PCB { int pid; // 进程唯一 ID,就像身份证号 char state; // 当前状态:'R'(就绪), 'W'(阻塞), 'E'(执行) int priority; // 优先级,决定谁先抢到 CPU int pc; // 程序计数器,记录下一条要执行的指令地址 int *stack_ptr; // 栈指针,指向当前函数调用的栈顶 struct memory_map *mm; // 内存映射,记录它占了哪些内存页 struct file_descriptor *fd; // 文件描述符表,记录它打开了哪些文件 };- 为什么必须有 PCB?
没有它,CPU 切走一个进程再切回来时,根本不知道刚才算到哪一步、变量存在哪、栈顶在哪——一切归零。PCB 就是它的“记忆备份”,每次切换,操作系统先保存当前 PCB,再加载下一个 PCB,进程就能无缝续上。
3.3 进程的五态模型:一张图看懂“它为什么卡住”
课本的“三态图”(就绪/执行/阻塞)是基础,但实际更复杂。加入创建、终止、挂起后,才是真实世界:
| 状态 | 触发条件 | 关键特征 |
|---|---|---|
| 新建态 | fork()系统调用刚创建进程 | PCB 已建,但还没进就绪队列,资源未分配完 |
| 就绪态 | 创建完成 / 阻塞结束 / 时间片用完 | 万事俱备,只差 CPU,排在就绪队列里等 |
| 运行态 | 调度器选中它,CPU 开始执行 | 真正干活,占用 CPU |
| 阻塞态 | 主动请求资源(如read()等键盘) | CPU 让给别人,自己挂起等事件(如按键) |
| 终止态 | exit()或被kill()杀死 | 资源已回收,PCB 待销毁 |
| 挂起态 | 内存紧张,被换出到外存(swap out) | 进程暂停,但 PCB 还在内存,可快速恢复 |
关键洞察:进程卡在“阻塞态”,不是系统坏了,而是它在主动等待外部事件(如用户输入、网络包到达)。这是异步性的体现,也是提高 CPU 利用率的关键——与其让它干等,不如让别人先干。
4. 进程同步与互斥:当多个进程抢同一把“钥匙”,如何避免混乱?
4.1 临界资源与临界区:冲突的源头,必须画出“警戒线”
临界资源(Critical Resource):一次只能被一个进程使用的资源。
典型例子:打印机、共享内存中的某个变量、数据库连接池。就像公司里唯一的会议室,不能 A 在开会 B 也冲进去。临界区(Critical Section):每个进程中,访问临界资源的那一段代码。
比如 A 进程的print_report()函数里,有“打开打印机→发送数据→关闭打印机”三步;B 进程也有同样三步。这六行代码就是两个临界区。如果 A 执行到“发送数据”一半,CPU 切给 B,B 也打开打印机……结果就是两份报告混成一团废纸。
核心原则:对同一临界资源,任何时候最多只有一个进程在它的临界区内。这叫“互斥”。
4.2 信号量(Semaphore):操作系统发的“电子取号机”,P/V 操作是取号/销号
信号量本质是一个整数变量 S,但它只能通过两个原子操作(不可打断)来修改:
wait(S)或P(S):申请资源。“取号”——如果 S > 0,S 减 1,进程继续;如果 S == 0,进程立刻阻塞,进入等待队列。signal(S)或V(S):释放资源。“销号”——S 加 1;如果等待队列里有进程,唤醒一个。
// 用信号量实现打印机互斥(mutex = 1) int mutex = 1; // 互斥信号量,初值为 1,表示打印机空闲 // 进程 A 的代码 P(mutex); // 取号:若 mutex==1,则变为0,A 进入临界区;若 mutex==0,A 排队 print_to_printer(); // 临界区:真正打印 V(mutex); // 销号:mutex 变回 1,唤醒排队者(如有) // 进程 B 的代码(完全一样) P(mutex); print_to_printer(); V(mutex);- 为什么 P/V 必须是原子操作?
假设P(mutex)不是原子的,它内部是“读 mutex → 判断是否>0 → 减1”。如果 A 读到 mutex=1,正要减1时被切走,B 也读到 mutex=1 并减为0,结果两个进程都以为自己拿到了钥匙——灾难!
4.3 常见误区与易混概念:别再被“同步”“互斥”“死锁”绕晕
| 易混点 | 为什么混? | 怎么清晰区分? |
|---|---|---|
| “同步”和“互斥”是一回事? | 都用信号量,都涉及进程等待。 | 互斥(Mutual Exclusion)解决“谁能用”的问题(保护临界资源);同步(Synchronization)解决“谁先谁后”的问题(如生产者必须先造出产品,消费者才能取)。互斥是同步的基础,但同步范围更广。 |
| “死锁”就是“卡死”? | 看到进程不动,就喊“死锁了”。 | 死锁(Deadlock)是一种特定僵局:4 个条件同时满足(互斥+请求保持+不可抢占+循环等待)。普通阻塞(如等键盘)是正常状态,有外部事件就能唤醒;死锁是永久僵持,无外力无法解开。 |
| “管程”比“信号量”高级,所以更好? | 课本说管程“封装性好”,信号量“容易出错”。 | 信号量是底层原语,灵活但易错(P/V 必须成对,漏一个就出事);管程是高级抽象(把共享变量+操作打包),强制“一次只允许一个进程进入”,更安全。但管程本质还是用信号量实现的——它不是替代,而是封装。 |
| “银行家算法”能预防所有死锁? | 听名字像万能保险。 | 银行家算法是“避免”(Avoidance),不是“预防”(Prevention)。它要求进程提前声明最大需求,系统动态检查每次分配后是否仍存在“安全序列”。如果进程撒谎或需求突变,算法就失效。它牺牲了灵活性换安全性。 |
| “虚拟内存”就是“内存不够用时用硬盘凑”? | 简化理解导致误解。 | 虚拟内存不仅是“扩容”,更是内存管理范式革命:它让每个进程拥有独立、连续的地址空间(0x00000000~0xFFFFFFFF),而物理内存可以是碎片化的;它提供内存保护(进程A不能读进程B的内存);它支持按需调页(只加载用到的页面)。硬盘只是实现手段之一。 |
5. 存储管理:从“内存像一块大黑板”到“每个进程都有自己的小房间”
5.1 为什么需要分页?——告别“内存碎片”的噩梦
早期系统用“连续分配”(如固定分区),就像租写字楼:把整层楼划成 10 个固定大小的办公室。问题来了:
- 小公司(程序)只用 20㎡,硬塞进 100㎡ 大间,浪费 80㎡;
- 大公司(程序)要 120㎡,但最大空闲间才 100㎡,只能干瞪眼;
- 更糟的是,退租后留下无数 5㎡、10㎡ 的碎空隙,再也租不出去——这就是外部碎片。
分页(Paging)彻底改变思路:把内存和程序都切成固定大小的小块(页/页框),比如 4KB 一页。程序不再需要“连续的大房间”,只要把它的各页,分散装进内存里任何空闲的页框就行。
程序逻辑地址(32位)示例: 0x12345678 假设页大小 4KB = 2^12 字节 → 页内偏移量占低12位(0x000~0xFFF) → 页号 = 0x12345678 >> 12 = 0x12345 (高20位) → 页内偏移 = 0x12345678 & 0xFFF = 0x678操作系统维护一张页表(Page Table),记录每个页号对应哪个物理页框号。CPU 访问地址时,硬件自动查页表做转换——对程序员完全透明。
5.2 快表(TLB):CPU 的“内存地址速查手册”,解决二次访存瓶颈
分页有个致命问题:每次访问数据,CPU 要先查页表(内存中)得到物理地址,再用物理地址去内存取数据——两次内存访问,速度腰斩。
快表(Translation Lookaside Buffer, TLB)就是 CPU 内置的高速缓存,专门存最近用过的“页号→页框号”映射。90% 的地址转换,TLB 一查就中(命中),直接拿到物理地址,省去一次内存访问。
- TLB 命中率 95%,访问内存有效时间(EAT)计算:
设 TLB 查找时间 1ns,内存访问时间 100ns:EAT = (1+100)×0.95 + (1+100+100)×0.05 = 105.5 + 10.05 = 115.55ns
若无 TLB,EAT = 100+100 = 200ns。快表让速度提升近一倍。
5.3 页面置换算法:当内存满了,“踢谁出去”最聪明?
程序越开越多,内存总有装不下的时候。操作系统必须选一个“不太重要”的页面,换到硬盘(swap out),腾出页框给新页面。选谁?算法决定系统流畅度:
| 算法 | 核心思想 | 优缺点 | 为什么现实不用? |
|---|---|---|---|
| FIFO(先进先出) | 踢最早装入内存的页 | 实现简单 | Belady 异常:增加内存页框数,缺页率反而上升!违背直觉,性能差。 |
| OPT(最佳置换) | 踢未来最久不用的页 | 理论最优,缺页率最低 | 无法预知未来,纯理论标杆,用于评估其他算法。 |
| LRU(最近最少使用) | 踢最久没被访问的页 | 接近 OPT,效果好 | 硬件实现成本高(需为每页记时间戳/链表),常用近似算法(Clock)。 |
| Clock(时钟算法) | 用环形链表+访问位(A位),像钟表扫过,A=0 就踢 | 硬件开销小,效果接近 LRU | 主流选择。Linux 的kswapd进程就基于改进 Clock(加修改位M)。 |
血泪经验:考试爱考 FIFO/LRU 对比,但实际开发中,你永远不需要手写置换算法——那是内核的事。你需要懂的是:为什么会有缺页中断?为什么频繁 swap 会导致系统卡成PPT?因为硬盘比内存慢 10 万倍,一次 swap 就是 10ms 级别的延迟。
6. I/O 管理与虚拟设备:让慢速外设不拖垮整个系统
6.1 I/O 控制方式演进:从“CPU 苦力工”到“智能管家”
外设(键盘、硬盘、网卡)比 CPU 慢几个数量级。如果让 CPU 亲自盯着它们干活,效率极低:
- 程序控制 I/O(轮询):CPU 死循环问硬盘:“好了吗?好了吗?好了吗?”——CPU 100% 浪费在等待上。
- 中断驱动 I/O:CPU 发指令后去干别的,硬盘干完发个“叮!”(中断信号),CPU 才停下处理。效率飞跃,但每次中断都要保存/恢复 CPU 环境,开销不小。
- DMA(直接内存访问):引入 DMA 控制器。CPU 只需告诉 DMA:“把硬盘第1000扇区数据,搬到内存地址 0x100000”,DMA 自己搞定搬运,完成后才中断 CPU。CPU 干预从“每字节一次”降到“每块一次”,效率再升。
- I/O 通道:更进一步,通道是“专管 I/O 的小 CPU”。CPU 只需发一条命令:“执行通道程序(含一连串读写指令)”,通道自己解析执行。CPU 干预降到“每批任务一次”,适合大型机。
6.2 SPOOLing 技术:把独占打印机,变成人人可用的“云打印”
打印机是典型独占设备——A 打印时,B 只能等。SPOOLing(Simultaneous Peripheral Operations On-Line)用“空间换时间”,把它虚拟成共享设备:
SPOOLing 系统四件套: 1. 输入井/输出井:硬盘上的大文件夹(模拟脱机磁盘) → 输入井:存所有待处理的输入数据(如键盘录入的文本) → 输出井:存所有待打印的文件(如 Word 文档) 2. 输入缓冲区/输出缓冲区:内存中的小中转站 → 缓冲区:暂存从键盘来的数据,防 CPU 处理不过来 3. 输入进程/输出进程:后台守护程序 → 输入进程:不断把键盘数据写入输入井 → 输出进程:不断从输出井取文件,发给打印机 4. 井管理程序:调度中枢 → 用户打印时,它把文件拷贝到输出井,加入打印队列 → 输出进程按队列顺序,逐个取文件交给打印机效果:用户点击“打印”,瞬间返回(文件已入井);打印机在后台慢慢吐纸。A、B、C 三人同时打印,系统自动排队,打印机成了“公共资源”。
6.3 什么时候该用 SPOOLing?什么时候不该用?
该用:
✅ 设备速度远低于 CPU(打印机、老式绘图仪)
✅ 多用户/多任务环境(服务器、实验室机房)
✅ 需要提高设备利用率(避免打印机空闲,而用户在等)不该用:
❌ 实时性要求极高(如工业控制,打印命令必须 1ms 内响应)——SPOOLing 增加延迟
❌ 设备本身已支持高速缓冲(现代 USB 打印机自带大缓存)——画蛇添足
❌ 内存/磁盘空间极度紧张(SPOOLing 需要大量外存空间)
从那以后我每次看到“独占设备”这个词,第一反应不是背定义,而是问自己:它慢在哪里?能不能用缓冲+队列+后台进程,把它变成“看起来”是共享的?这个思维习惯,让我在分析磁盘调度(SCAN 电梯算法)、网络协议(TCP 滑动窗口)时,一下就抓住了本质——操作系统所有的“高级技巧”,不过是把“慢”藏起来,把“等”变成“并行”。希望帮到你。
本文还有配套的精品资源,点击获取