书 · 2018-08 · 雷姆兹·阿帕奇-杜索(Remzi H. Arpaci-Dusseau)、安德莉亚·阿帕奇-杜索(Andrea C. Arpaci-Dusseau)

《操作系统导论》

计算机与 AI书单第 45 名

一句话结论

操作系统通过虚拟化、并发控制和持久化,把有限、共享、可能出错的硬件变成程序能够方便使用的资源,而每种便利背后都有成本与取舍。

值不值得读完整本?

值得读完整本,尤其适合想弄清程序如何实际运行、数据如何可靠保存的读者;但要配合推演和编程,单靠读懂文字很容易高估自己的理解。

  • 先读第2章建立全貌,再按处理器虚拟化、内存虚拟化、并发、持久性的顺序推进;本卡章节号采用2018年英文正式版目录,与中文译本不完全对应。
  • 重点细读第4—9章、第13—23章、第26—32章和第39—45章,分别掌握进程与调度、地址转换、同步、文件系统与恢复。
  • 第一遍可以暂缓第10章多处理器调度和第33章基于事件的并发;对话章可快速阅读,用来检查自己能否说清前面的问题。
  • 第36—38章的设备与磁盘阵列知识有助于理解存储性能,第48—50章则把缓存、故障和一致性问题扩展到多台机器,建议第二遍补齐。
  • 配合调度和分页模拟作业,运行线程计数器、生产者与消费者程序,并画出文件系统更新过程中各次写入后的状态。

核心观点

1. 处理器虚拟化要兼顾运行效率、控制权与调度目标

操作系统让多个进程轮流使用处理器,形成各自持续运行的体验。如何安全切换是机制问题,轮到谁运行以及运行多久是策略问题。

为什么:让普通指令直接在处理器上执行,可以避免逐条模拟的开销。硬件权限限制危险操作,系统调用提供受控入口,定时器中断让内核能够重新取得控制权。保存和恢复执行状态后,进程就能从暂停处继续运行。但切换能力本身不能决定最佳调度:缩短平均周转时间、改善首次响应和保证资源份额,可能要求不同的安排。

2. 虚拟内存用地址间接映射换取隔离与灵活分配

程序使用的是自己的虚拟地址空间,实际数据可以分散在物理内存中,部分页面还可以暂存在外部存储上。地址转换使程序看到的布局与硬件上的布局分开。

为什么:如果程序直接决定物理地址,多个进程就容易互相覆盖,也难以搬移和保护内存。分页把地址空间切成固定大小的页,通过页表记录映射和访问权限,从而支持分散分配与受控共享。转换后备缓冲器缓存常用映射,减少每次访问都查页表的成本。不在内存中的页面可以在访问时调入,但缺页代价很高,因此性能取决于程序的局部性、可用内存和页面替换策略。

3. 并发正确性取决于允许哪些交错,而不只是代码执行顺序

多个线程共享状态时,源码中的一个操作可能由多条机器指令完成。锁解决互斥访问,条件变量和信号量帮助表达线程之间的等待关系。

为什么:线程可能在读取、修改和写回之间被切换,因此分别正确的操作交错后仍会丢失更新。锁把相关操作组织成临界区,限制破坏共享状态的交错。互斥并不能自动表达“缓冲区非空才能取数据”这样的条件,等待还需要与状态检查协调。条件变量等待时原子地释放锁并进入等待,醒来后重新加锁检查条件;而锁的使用若形成循环等待,又可能造成死锁。

4. 存储性能来自数据布局、访问模式与设备特性的配合

文件系统把文件和目录组织成磁盘上的数据与元数据,并通过缓存、布局和批量处理降低访问成本。不同设备和负载下,有效的优化方式会改变。

为什么:机械硬盘的寻道与旋转等待,使分散的小请求往往比连续传输昂贵,因此把相关数据放近可以减少等待。内存缓存吸收重复读取,也能把多次修改合并后写出。日志结构文件系统进一步把分散修改汇集为顺序写入,但旧版本占用的空间需要清理,清理本身也会消耗带宽。固态硬盘没有机械寻道,却有擦除和写入方面的限制,所以不能直接套用全部硬盘经验;磁盘阵列同样要在容量、性能与冗余之间取舍。

5. 可靠持久化必须分别处理崩溃一致性与数据损坏

数据保存在非易失设备上,并不代表更新过程天然可靠。文件系统既要避免崩溃留下相互矛盾的结构,也要发现设备返回的内容是否已经损坏。

为什么:一次文件操作可能修改数据块、索引信息和空闲空间记录,这些写入并不会天然作为整体完成。若中途崩溃,只完成部分写入就可能破坏结构关系。日志通过规定记录、提交和后续更新的顺序,让恢复程序识别可重放的完整事务,减少全盘检查的需要。但结构一致并不保证每个数据块内容正确,校验和用于发现损坏,冗余副本则可能提供修复来源;检测、恢复与应用要求的持久性仍需分别设计。

6. 分布式文件系统用缓存扩展服务,也必须明确故障与一致性语义

把文件访问扩展到网络后,接口可以保持熟悉,但延迟、消息丢失和独立故障会改变实现条件。缓存与协议设计共同决定系统能服务多少客户端,以及读者何时看见修改。

为什么:远程访问需要通信,服务器还可能在客户端仍运行时崩溃,因此一次没有回复的请求未必没有执行。协议必须考虑重试、重复请求和恢复,而不能直接套用本地函数调用的假设。客户端缓存减少通信和服务器工作,却产生副本何时失效的问题。频繁验证缓存可以限制陈旧程度,但会增加负载;回调等机制减少反复查询,同时要求维护相应状态并处理故障。

反对意见

Unix实例与通用原理的边界不够清楚(Dan Luu)

Dan Luu在《Programming book recommendations and anti-recommendations》中肯定本书解释清楚、文件系统部分深入,同时认为它过于偏重Unix,未充分区分通用原理与具体系统的选择。这提醒读者:理解书中的进程和文件接口后,还需要判断哪些属于普遍问题,哪些属于一种历史实现。该评论针对正式1.0版之前的版本。

同步入门不能替代内核实现训练(Grzegorz Bielski)

Grzegorz Bielski在《Operating Systems; Three Easy Pieces - review》中认为,并发篇更多围绕用户态同步,较少深入内核内部实现;他也指出启动、网络接口和容器等主题覆盖不足。这是对学习范围和教学安排的个人评价,说明读完本书仍需要实现课程或源码阅读,而非证明书中的同步原理有误。

顺序写入的好处可能被清理成本抵消(Margo Seltzer等)

Margo Seltzer等人在《File System Logging versus Clustering: A Performance Comparison》中比较日志结构与聚簇布局,指出日志结构并不普遍产生数量级的性能提升,结果取决于负载和清理成本。这是对书中所讨论技术路线的适用范围提出检验,并非直接反驳本书;本书也介绍了这场争论。

资源管理策略未必应该由内核统一提供(Dawson R. Engler等)

Dawson R. Engler等人在外核论文中主张,让内核主要负责资源保护和复用,把更多资源管理交给应用层库。其理由是固定的高层抽象可能隐藏应用能够利用的信息,限制专门优化。这与本书大量讲授的传统组织方式形成架构上的对照,追问的是抽象和策略应该放在哪里,并非否认保护与共享的必要性。

相关推荐

导读由 AI 根据公开资料整理,没有读取原书全文,一切以原著为准。导读 Primer 首页