操作系统导论(OSTEP)笔记答案代码:从解压到运行模拟器的避坑全攻略

发布时间:2026/9/28 11:58:36
操作系统导论(OSTEP)笔记答案代码:从解压到运行模拟器的避坑全攻略 简介这是一份以《操作系统导论》(OSTEP)为核心的完整学习资料包面向计算机专业学生、考研复习者及自学操作系统的读者涵盖进程管理、内存管理、文件系统、I/O设备控制等核心专题并配有课后习题答案与可运行的实验代码帮助解决理论学习与动手实践脱节的问题。压缩包内共294个文件以97个Markdown笔记、71个C源码、33个Python脚本、19个头文件、13个Makefile为主体另有汇编程序、README说明与少量图片整体约902KB目录层次清晰便于按模块快速定位。该资源已有82人学习下载适合计算机专业学生作为课堂辅助考研准备者用于系统梳理也适合业余自学者按章节推进或针对薄弱环节单独查阅。针对进程调度、虚拟内存、同步互斥、文件系统设计等难点既有结构化笔记也有可直接运行的调度模拟、内存分配与文件系统操作代码配合习题答案验证思路能显著提高课后练习与实验效率尤其适合在课程设计或实验报告中参考。1. 操作系统导论(ostep)笔记_课后习题答案_附加代码.zip一个打包成zip的操作系统学习闭环你手上这个《操作系统导论(ostep)笔记_课后习题答案_附加代码.zip》并不是让你跳过学习的捷径包。我第一次拿到时也以为笔记省了整理、答案省了推导。真正打开跑了一遍才发现值钱的部分反而是最后那个“附加代码”——OSTEP的课后作业几乎都围绕这些小模拟器和示例程序设计没有它们笔记里的调度算法、并发同步、页面置换永远停留在纸面。我下面顺着这个zip包的三块内容往下拆怎么把笔记读薄、怎么用答案做验证、怎么把附加代码在Linux操作系统上跑通以及我踩过的坑。适合正在学操作系统课程、期末复习或转码补基础的人。2. 拆开zip先别急着对答案用ostep笔记把操作系统读薄OSTEP 这套资料流传很广但很多人拿到的是一堆没整理的散乱文件目录层级乱得让人不想打开。我的建议是解压后第一件事不是翻答案而是先建立“笔记 - 课后题 - 附加代码”的对应关系。如果你一上来就对着答案看最多半小时就会丢失目标因为答案只能告诉你“是什么”不能告诉你“为什么改一个参数结果就翻车”。2.1 解压前先看zip内容清单识别版本和缺文件的信号最常见的错误是拿到zip立刻双击解压。我一般会先用unzip -l把清单列出来因为OSTEP资料包流传的版本很多有的整理者会把模拟器脚本漏掉有的会把答案按章节拆开。先看清单能省掉后面一半的坑。unzip -l 操作系统导论(ostep)笔记_课后习题答案_附加代码.zip | head -80unzip -l只读取压缩包的中央目录不实际解压文件所以执行很快。head -80限制输出行数避免目录太长刷屏。这里有两个细节要注意第一zip 文件名里带括号和小写英文在 bash 中必须用双引号包起来否则(会被当成子 shell 语法第二观察输出的重点不是文件名本身而是目录结构和文件后缀。我会重点看三件事第一层目录有没有notes/、answers/、code/或homework/这类清晰划分文件后缀是否包含.py、.c这代表了附加代码是否完整有没有个别文件明显比其他文件小很多例如scheduler.py只有几 KB 但目录里却没看到那很可能是被精简掉了。如果一个资料包只有 PDF 笔记和答案没有.py脚本那它不是一个完整的 OSTEP 学习包因为书里大量作业题都要求运行模拟器。2.2 读笔记的正确姿势按“虚拟化-并发-持久化”三条主线做勾联OSTEP 原书不是教科书式写法它用“三个简单片断”讲操作系统虚拟化、并发、持久化。市面上的 OSTEP 笔记多数是按原书章节提炼的要点、图表和代码片段。但笔记只是别人嚼过的内容不能替代原书。我的做法是先读一章原书再打开对应笔记把笔记里每条要点对应到书里的一个故事或一个例子。比如讲调度那一章书里用顾客排队买咖啡的例子引入策略笔记里如果只写“SJF Shortest Job First”没有用。你要能直接说出当作业同时到达时SJF 能最小化平均周转时间当作业陆续到达时SJF 可能让长作业饿死。再比如虚拟化章节里的地址翻译笔记里画了两张页表但真正需要理解的是“TLB 命中一次翻译没命中就要走页表遍历”这个流程用模拟器跑一次比背十遍笔记都管用。我看笔记时会在旁边补三个记号虚线框代表书中的例子箭头指向对应机制星号代表需要自己跑模拟器验证。这个习惯能让一份外部笔记变成自己的复习地图也避免期末对着答案却想不起原理。如果你是准备考试建议把笔记的每个章节标题都转成一句“我能干什么”例如“我能用 FIFO 和 SJF 算平均周转时间”而不是“这章讲调度”。2.3 笔记和课后习题答案的对应关系哪些是复习题哪些是作业题OSTEP 每章末尾有两种题复习题和作业题。复习题是简答类例如“上下文切换时硬件保存了什么操作系统保存了什么”作业题则要求你运行该章附带的模拟器观察参数变化。常见资料包里的答案往往混在一起如果不区分会踩一个坑你把复习题答案背得滚瓜烂熟却不知道作业题的答案长什么样。复习题答案可以在笔记里直接用作业题答案则必须配合命令复现。主题核心章节示例常见作业形式笔记里该补什么虚拟化进程、CPU调度、地址空间、页表运行 scheduler.py、paging-policy.py 改参数调度算法和页面置换算法的流程以及每个参数对结果的影响并发锁、条件变量、信号量编译运行 thread.c 等 C 程序临界区、死锁触发条件、锁的竞争开销持久化文件系统、RAID、日志运行 fsck.py、raid.py 模拟器磁盘布局、RAID 级别容错计算这个表格不是用来背的而是用来检查资料包是否完整。如果一个章节对应的.py脚本缺失你很难完成作业题。复习题可以靠笔记回答但作业题必须靠代码跑出结果。答案的用途是给作业题提供一个基准输出但你最好先自己算一遍再让模拟器当裁判。这正是下一章要展开的操作。3. 课后习题答案的几种正确用法先自己算再让模拟器当裁判很多人拿答案当“黑匣子”只看最终数字却不关心数字怎么来的。OSTEP 的作业题和普通习题集不同它给的是模拟器输入参数不是固定题目所以答案并不是唯一解释权可复现的代码才是。这里我按自己用过三轮的经验把答案的用法分成三个层次。3.1 答案只是参照系先自己推导再对答案错题才长本事以调度章节为例作业题通常给你一组进程的到达时间和服务时间让你计算 FIFO、SJF、RR 的平均周转时间或平均响应时间。如果你直接翻答案只记住了那个数字换一组负载又不会了。正确流程是这样的打开笔记或原书确认公式。周转时间等于完成时间减到达时间响应时间等于首次运行时间减到达时间。用表格手算或者用 Python 写一个小脚本算。跑模拟器加-c参数让模拟器打印计算结果。拿自己的结果和答案对比。如果一致说明思路对如果不一致先别急着怀疑自己答案也有可能是旧版模拟器算的。OSTEP 各版次会改作业题模拟器也会更新资料包里的答案经常是几年前的数字对不上很正常。我见过最典型的例子是书里的作业题要求进程数量-j 3但答案贴出来的表却是-j 5明显是整理答案的人自己改过参数。这时候你按原题跑永远对不上。所以我把答案定位成“参照系”不是“标准答案”。它能帮你确认章节重点但真正长本事的是你在对答案之前做的那次推导。错题也只有在你先动过脑之后才有价值直接背答案等于没做。3.2 用一段Python复现“作业题”结果以调度模拟器为例我一直觉得能用十行 Python 手算一道调度题比拿着答案背十遍更有用。下面这段脚本模拟非抢占式 FIFO 调度输入是一个进程列表每个元素是“到达时间, 服务时间”# fifo_avg_turnaround.py # 输入进程到达时间和服务时间列表 jobs [(0, 100), (10, 10), (10, 10), (10, 10)] # (arrival, burst) time 0 completion [] for arrival, burst in jobs: if time arrival: # 如果CPU空闲到该进程到达 time arrival # 时钟跳转到到达时间 time burst # 执行该进程 completion.append(time) # 记录完成时间 turnaround [c - a for c, (a, _) in zip(completion, jobs)] print(完成时间:, completion) print(平均周转时间:, sum(turnaround) / len(turnaround))这段代码的逻辑很直接按作业列表顺序执行如果当前 CPU 时间小于下一个进程的到达时间说明 CPU 在空闲就把时钟跳到到达时间。完成时间减去到达时间就是周转时间。输出的平均周转时间就是作业题要的那个数。你可以修改jobs里的数字做不同实验也可以把列表按服务时间排序来模拟 SJF。但这里有个坑SJF 在进程同时到达时才生效如果到达时间不同简单排序不一定是真正的 SJF 结果。所以更可靠的方式是直接跑官方模拟器在作业目录下执行python3 scheduler.py -p FIFO -l 0,100,10,10,10,10 -c-p指定调度策略-l后面的数字每两个一组分别是到达时间和服务时间-c让模拟器计算出统计结果。注意如果没有-c模拟器只画执行顺序图不会打印平均周转时间。这就是答案背后真正的计算过程。3.3 当答案和你算的不一致按参数和随机种子逐行核对我和不少同学交流过发现“答案对不上”这种事十有八九是参数问题。最典型的是作业题里写-s 3 -j 5你随手跑一个-s 1结果当然不一样。OSTEP 模拟器的随机种子-s控制进程集合种子不同生成的作业表就不同。答案往往只对应题目给出的那个种子换一个就面目全非。排查时我会按这个顺序来第一步用python3 scheduler.py -h查看当前模拟器的参数名确认-s、-j、-l、-c的定义和答案使用的方式一致。第二步确认题目问的是平均周转时间还是平均响应时间这两个指标在同一份输出里都会出现答案可能只抄了其中一个。第三步检查负载列表的顺序同样是三个进程FIFO 和 SJF 的顺序不同结果就不同。第四步如果题目用的是随机进程集合必须固定随机种子再跑不固定的话每次结果都不同。如果以上都对不上最终裁判是模拟器的-c输出而不是答案文本。答案整理者和你用的模拟器版本不一样这种情况在老旧资料包里太常见了。你要相信代码的可复现性而不是某份无法考证的答案。这也提醒我每次跑作业题时把使用的命令、随机种子和关键输出都保留下来免得以后回来看自己都不知道当时怎么算的。4. 把附加代码在linux操作系统上跑通scheduler.py与C示例的编译运行附加代码是整套资料里最容易被浪费的部分。很多人以为它是可有可无的源码实际上它是 OSTEP 作业的“命题载体”。如果你在 Windows 上直接双击.py文件大概率只闪一下黑窗就没了。我推荐在 Linux 操作系统上跑或者用虚拟机、WSL 装一个 Ubuntu这样命令和书里完全一致避免“我的环境不行”这类干扰。4.1 附加代码的组成python模拟器、C示例、shell工具OSTEP 的附加代码可以分成两类。第一类是模拟器通常是单个 Python 脚本用来生成调度、分页、RAID 等场景。它们依赖很少基本只用标准库所以只要有一个 Python 解释器就能跑。第二类是书里讲解用到的短 C 程序比如进程创建、多线程、锁和信号量这些需要一个 C 编译器。不同资料包的目录命名差别很大有的叫homework/有的叫ostep-code/还有的直接把脚本和笔记放同一层。不要预设目录先跑一条查找命令find . -name *.py -o -name *.c | sort | head -30这条命令会在当前目录递归找出所有.py和.c文件sort让输出有规律head -30截断前三十行。看到文件列表之后你就能判断附加代码的完整度。如果调度章节找不到对应的.py说明资料包不完整后续作业只能靠手算学习效果大打折扣。我在实际使用时会为这套资料单独建一个 Python 虚拟环境不是因为这些脚本需要特定依赖而是系统 Python 环境可能被改得很乱用虚拟环境可以保证python3指向干净的解释器。这只是个习惯不是必须步骤但能少踩很多版本坑。4.2 跑通第一个模拟器scheduler.py 的启动命令与参数解读我建议第一个跑通的是调度模拟器scheduler.py因为它输出简单、参数直观能立刻让你看到调度策略的区别。假设你已经找到脚本所在目录执行cd 解压目录/homework/scheduling python3 scheduler.py -p FIFO -l 0,100,10,10,10,10 -v -c这里的解压目录要根据你的实际路径替换。命令中-p FIFO指定调度策略-l后面是负载列表每两个数字一组到达时间、服务时间所以0,100表示进程在时间 0 到达需要运行 10010,10表示进程在时间 10 到达需要运行 10。-v打开详细输出-c让模拟器计算并打印统计结果。如果你看到的是 Python 语法报错先别慌下一章会说怎么处理。跑通之后试着把-p FIFO改成-p SJF或-p RR再做同样的负载观察平均周转时间怎么变。我第一次跑的时候发现 SJF 在这个负载下的平均周转时间比 FIFO 还高吓了一跳。后来才意识到SJF 的优势只在所有进程同时到达时成立当到达时间错开晚到的短作业会让先到的长作业继续等反而拖慢整体完成时间。这个结论如果只看笔记是记不住的跑一遍才会留下肌肉记忆。4.3 编译并运行一个C示例以并发中的线程创建为例C 示例部分需要的不是 Python而是 gcc 编译器。OSTEP 并发章节的示例代码常常依赖common_threads.h这个头文件它封装了线程创建、互斥锁的基本调用。直接gcc thread.c大概率会报“找不到头文件”因为头文件被放在独立的 include 目录里。# 假设示例代码在 code/threads 下头文件在 code/include 下 gcc -o thread_example code/threads/thread.c -I code/include -lpthread ./thread_example-I code/include告诉编译器去code/include目录查找头文件这样#include common_threads.h才能命中。-lpthread链接 POSIX 线程库有些示例只写了pthread_create不写这一项编译时会报“未定义引用”错误。-o thread_example指定输出文件名运行./thread_example就能看到结果。如果你用的是全新 Ubuntu 操作系统第一件事是安装编译工具链不然连gcc命令都不存在。执行sudo apt install build-essential python3build-essential包含 gcc、make 等基础工具python3则保证模拟器脚本能跑。这个准备步骤很多新手会漏直到敲gcc -v才发现系统里根本没有编译器。装好之后再去编译 C 示例就不会卡在第一步。5. 从zip解压到跑通模拟器的避坑检查单5个现象、原因与解决这一章的每一条都是我在不同操作系统、不同资料包版本里真实遇到过的。按“现象 - 原因 - 解决”写方便你遇到问题直接对照。5.1 zip解压失败或提示伪加密下载不完整或压缩包被“加壳”现象在 Linux 下执行unzip xxx.zip中途报错error: Central directory file header not found或者某个文件解出来是零字节。在 Windows 下用 WinRAR 打开它要求输入密码而你在资源页没看到密码。原因一部分是下载时网络中断zip 文件尾部缺少中央目录unzip无法解析。另一部分是被“伪加密”处理过打包工具修改了 zip 的加密标志位让工具以为文件加密了但数据本身并没有加密。OSTEP 资料本身是开源公开的正常情况下不会加密遇到密码提示基本可以怀疑是伪加密或二次打包。解决先测试压缩包完整性。Linux 下用 7z 测试7z t 操作系统导论(ostep)笔记_课后习题答案_附加代码.zip如果 7z 提示End of archive相关错误重新下载原包。如果是伪加密7z x可以直接解压因为 7-Zip 会尝试忽略加密标志位。系统自带的unzip对加密标志位检查更严格所以优先用 7z。服务器上如果没有 7z需要先装p7zip-full。这条经验帮我救回来过好几个号称“损坏”的资料包。5.2 python脚本在python3下直接报语法错误模拟器还是python2现象运行python3 scheduler.py时报错SyntaxError: Missing parentheses in call to print或者NameError: name xrange is not defined。原因OSTEP 早期的模拟器脚本基于 Python 2 编写而现代发行版默认只有 Python 3。这不是代码坏了是解释器版本不对。很多两年前下载的资料包里这类脚本基本都是 Python 2 风格。解决优先看系统里有没有python2命令python2 scheduler.py -h如果没有用2to3把脚本转换成 Python 3 语法cp scheduler.py scheduler_py3.py 2to3 -w scheduler_py3.py python3 scheduler_py3.py -hcp先复制一份备份避免2to3 -w原地覆盖原文件后找不到原始版。转换后建议逐个脚本跑一遍因为2to3不一定能把所有兼容性差异都处理干净尤其是一些老的print和range混用情况。我一般只转换当前要用的脚本不整个目录批量转换否则可能引入新的问题。5.3 无图形环境跑不动turtle模拟器换无头参数现象运行某些带可视化界面的模拟器时比如地址翻译或页面置换相关脚本终端报TclError: no display name and no $DISPLAY environment variable。原因这些脚本使用 Python 的 Tkinter/turtle 图形库在 SSH 终端或云服务器上没有图形显示服务所以一启动就崩溃。这不是代码坏了是环境缺少显示设备。解决先看模拟器帮助里有没有“无头模式”参数很多 OSTEP 模拟器用-c或-s提供纯文本计算模式。在服务器上我一般这样做关掉一切图形相关参数只用计算模式运行反正作业题要的是数值不是动画。如果你在本地桌面环境确实想看图形可以安装 Tk 支持sudo apt install python3-tk装完再跑就不会报no display name了。要注意某些老脚本用的是 Python 2 的 Tkinter在 Python 3 下也会报错所以还要结合 5.2 的版本问题一起排查。5.4 编译C示例时找不到common头文件include路径没加现象对并发章节的 C 示例执行gcc thread.c报错fatal error: common.h: No such file or directory。原因书中的示例代码依赖common.h和common_threads.h这两个头文件它们通常被放在独立的include目录里而示例代码里用双引号#include common.h编译器默认只在当前目录和系统目录查找当然找不到。解决先用find确认头文件实际位置find . -name common_threads.h然后编译时加-I参数gcc -o thread_example thread.c -I ./include -lpthread-I ./include把头文件目录加入搜索路径。不要图省事在源码里写/绝对路径/common.h那样换一台机器就崩。正确做法是让编译命令通过-I控制依赖路径。如果示例还依赖某个common.c实现文件需要把实现文件也一起编译否则链接阶段会报“未定义引用”。5.5 运行结果和答案不一致先检查题目版本和随机种子现象你按答案里的参数运行模拟器输出却和答案贴的表格对不上数值看起来差得很随意。原因除了策略参数外最常被忽略的是版本差异。OSTEP 书籍不同版次会修改作业题模拟器也会更新资料包里的答案可能是根据上一版脚本算的。另一个原因是随机种子作业题常给-s 1、-s 34这类数字少了种子结果不可复现。解决第一步python3 scheduler.py -h查看参数确认-s、-j、-l是否和题目一致。第二步固定随机种子再跑一次。第三步在答案旁边标注“答案的模拟器版本”和“我用的版本”是否一致。如果数值差异很大直接以模拟器-c输出为准。答案里的趋势一般不会错但具体数字可能过时尤其是转载多轮的资料包。6. 进阶验证用附加代码批量跑调度对比实验检验你是否真读懂了只看单个策略的输出不算读懂能设计一个对比实验才说明你把参数和算法串起来了。我每次拿到新的 OSTEP 资料包都会先固定一个随机种子把相关章节的模拟器至少跑两遍。下面这个例子用三种策略对比同一组负载路径要按实际目录调整。for policy in FIFO SJF RR; do echo $policy python3 scheduler.py -p $policy -l 0,20,5,15,10,5 -c | grep Average turnaround done这个循环里只改-p负载列表始终是0,20、5,15、10,5三个进程所以是控制变量实验。grep Average turnaround过滤出平均周转时间方便把三种策略的输出并排对比。如果策略是 RR还可以加-q 2调整时间片大小观察时间片对响应时间的影响。跑完你会看到一个很有意思的结果在这个负载下SJF 不一定比 FIFO 好。原因不是书错了而是教科书场景通常假设所有进程同时到达当到达时间错开后晚到的短作业可能插队让先到的长作业继续等整体周转时间反而恶化。把这个现象写进笔记旁边你才算真正理解了调度。我习惯把每次实验用的命令、参数和输出行保留下来整理成一张自己的结果表然后在表格旁边写一句“我看到了什么为什么”。这样期末复习时不用重新跑只看表格就能回忆起当时的判断。这个习惯帮我节省了大量时间也让别人争论调度算法优劣时我能直接给出可复现的实验结果。希望这个流程也帮到你。本文还有配套的精品资源点击获取

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询