ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

操作系统实验全指南:环境搭建、核心模块与答辩避坑

操作系统实验全指南:环境搭建、核心模块与答辩避坑 简介西南科技大学计算机专业操作系统课程实验的配套资源面向选修操作系统实验课的本专科学生覆盖进程管理、内存管理、文件管理三大核心章节帮助解决课内实验缺乏可运行参考代码、对抽象机制理解不透彻的问题。资源共10个文件压缩包仅481KB含4个可执行exe程序、4个cpp源文件与1个c源文件另有1个文件系统相关文件exe可直接运行观察结果cpp/c代码用于学习进程调度、内存分配、文件目录管理等关键源码实现目录按实验一至三分开存放便于按需查阅。实验设计遵循课程常见要求例如进程创建与撤销流程、内存分配回收策略、文件系统逻辑结构与检索操作代码量精简但涵盖核心操作适合在Windows环境下编译调试也可作为二次开发或实验报告讨论的基础。目前已有89人学习下载对有实验紧迫需求又希望深入了解实现细节的同学这套小体积资源能提供从运行演示到代码阅读的完整参考显著提升实验准备效率。1. 西南科技计算机操作系统实验这份压缩包不是标准答案是评分标准如果你是西南科技大学计算机专业的学生手里这份“西南科技计算机操作系统实验.7z”解压出来通常不只是几份代码而是一套包含实验指导书、参考实现、报告模板和评分细则的资源包。很多同学把它当成标准答案复制、改名、提交结果答辩时被老师追问两句就露馅。这个反直觉的点值得你先想清楚这份包真正值钱的不是代码本身而是它把进程调度、内存管理、文件系统这三个抽象概念变成了看得见、能运行、可验证的具体任务。把这套实验完整做一遍收益不只是过一门课。它同时覆盖了考研复试里操作系统的手写代码题、入职面试常问的调度算法和页面置换以及你简历上“熟悉操作系统原理”这句话的底气。适合正在做这门课设的本科生也适合准备复试、想用一套小实验检验自己掌握程度的自学者。前提是从解压开始把环境、编译、运行、验证整条链路自己走通而不是直接抄答案。2. 先把环境立住从解压 .7z 到用虚拟机搭好 Linux 实验台2.1 解压 .7z 的正确姿势别双击完就完事拿到.7z文件第一个坑就是用系统自带的资源管理器双击。Windows 自带的解压工具对 7z 格式支持不完整遇到分卷或者文件名带中文的情况解出来可能是乱码目录甚至某些实验文件静默丢失。我一般会装一个 7-Zip然后用命令行解压这样每一步都可控。在 Linux 实验环境里先用 7z 命令测试压缩包完整性# 先切到压缩包所在目录 cd ~/Downloads # 测试压缩包是否损坏不实际解压 7z t 西南科技计算机操作系统实验.7zt是 test 的缩写这个命令会逐个读取压缩包里的文件做校验和比对几秒钟就能告诉你这份包是完整的还是有损坏。如果显示Everything is Ok再执行解压# 解压到 /home/student/os-lab 目录下 7z x 西南科技计算机操作系统实验.7z -o/home/student/os-lab注意-o后面直接跟路径中间不能有空格这是 7-Zip 命令行最容易踩的格式坑。x表示按完整路径解压会保留压缩包内部的目录结构如果用e解压所有文件会被扔到同一个目录文件名重复时会互相覆盖。解压之后第一件事不是看代码而是先看目录结构7z l 西南科技计算机操作系统实验.7z | lessl是 list不解压就能看到压缩包内部的完整文件清单。这个命令的价值在于你能在解压前就知道里面有没有 README、评分标准、实验指导书避免把整个包解压完才发现缺了关键文档。建议养成习惯任何课程资源包先 list、再 test、最后 x三步走完再动代码。2.2 虚拟机选型VMware Workstation 还是 VirtualBox操作系统实验要求 Linux 环境但你大概率不想为了四个实验就把主力机重装成 Ubuntu。常见的做法是用虚拟机隔离Windows 上跑 VMware Workstation 或 VirtualBox 都行选型建议看这张表对比项VMware WorkstationVirtualBox性能与图形加速更强3D 支持好一般够用快照与克隆功能完整操作直观支持需要命令行更稳命令行管理vmrunVBoxManage价格商业软件开源免费适合人群想省心、电脑配置够学生党、轻量使用我个人的习惯是如果只是跑这四个实验VirtualBox 完全够用还省得找激活码如果你后面还要在虚拟机里做内核编译、跑性能测试VMware 的磁盘和 CPU 调度更稳。但不管选哪个都要会用命令行启动和关闭虚拟机因为实验写到凌晨鼠标点图形界面点不动的时候一个命令结束进程比到处找关机按钮快得多。VMware 用 vmrun 管理虚拟机# 无界面启动后台启动适合远程和脚本调用 vmrun -T ws start /home/student/VMs/Ubuntu2004/Ubuntu2004.vmx nogui # 列出当前运行的虚拟机 vmrun -T ws list # 正常关机soft 相当于执行 guest 内部 shutdown vmrun -T ws stop /home/student/VMs/Ubuntu2004/Ubuntu2004.vmx softVirtualBox 对应命令# headless 表示不弹图形窗口后台运行 VBoxManage startvm os-lab --type headless # 拍快照相当于实验前的后悔药 VBoxManage snapshot os-lab take before-exp3 # 回滚到指定快照 VBoxManage snapshot os-lab restore before-exp3这里有个容易被忽略的点snapshot take一定要在实验代码改动之前做。我见过太多人改到一半发现方向错了想回退发现没有快照只能对着 git log 和记忆重建代码。虚拟机快照配合 git 提交是这类实验课最值得养成的两个习惯。2.3 在虚拟机里装 LinuxUbuntu、麒麟与一般性建议操作系统实验的参考实现多半是为 Linux 写的建议装 Ubuntu 22.04 LTS 这类长期支持版本。如果你所在学校用的是国产化平台麒麟操作系统Kylin和统信 UOS 的安装步骤也大差不差内核都是 Linux编译命令和实验行为一致。虚拟机里装系统有两点要注意一是 ISO 镜像下载后用校验工具对一下 SHA256二是安装时给虚拟机分配的资源别太小——CPU 给 2 核、内存给 2GB 就足够跑完这套实验用不着 8GB但你如果还想同时跑 IDE 和浏览器给 4GB 更从容。装完系统第一件事是换软件源否则 apt 下载工具能慢到让你怀疑人生。以阿里云源为例# 先备份原始源文件这是所有系统配置操作的默认习惯 sudo cp /etc/apt/sources.list /etc/apt/sources.list.bak # 把官方源替换为阿里云镜像源 sudo sed -i s|http://archive.ubuntu.com/ubuntu|https://mirrors.aliyun.com/ubuntu|g /etc/apt/sources.list # 更新索引 sudo apt updatesed命令里的|是分隔符因为 URL 里有/如果用默认的/做分隔符就要写一堆转义。这个细节在敲命令报错时最明显。换源之后安装编译工具链sudo apt install -y build-essential git valgrind gdb p7zip-fullbuild-essential包含 gcc、g、make 等一整套编译工具valgrind 和 gdb 是后面排查内存错误和段错误的利器建议一次装齐免得实验到一半再想起来缺工具。2.4 实验目录规划解压之后立刻建好工作区解压完的资源包不要直接在里面改代码把实验内容复制到自己的工作目录并建立清晰的目录结构。常见的做法是这样的os-lab/ ├── exp1_scheduler/ # 进程调度实验 │ ├── src/ │ └── test/ ├── exp2_memory/ # 内存管理实验 │ ├── src/ │ └── test/ ├── exp3_filesystem/ # 文件系统实验 │ ├── src/ │ └── test/ └── report/ # 实验报告和截图在 os-lab 根目录初始化 git 仓库每完成一个模块就提交一次cd os-lab git init git add . git commit -m 初始导入实验指导书与参考代码框架git 在这里起两个作用一是给每一次改动留后悔药二是答辩前你能git log展示从零到完成的全过程这比报告里写“我独立完成了”更有说服力。目录结构还有一个好处后面第 4 章的 Makefile 和回归测试脚本都依赖清晰的路径混乱的文件摆放会给自动化脚本带来一堆引号转义问题。3. 实验核心模块拆解进程调度、内存管理、文件系统分别怎么落地3.1 进程调度实验FCFS、SJF 与 RR 的代码骨架和时间片选择进程调度实验在课程里通常要求实现三种算法先来先服务FCFS、短作业优先SJF和时间片轮转RR。写代码之前先把输入输出格式想清楚输入是若干进程的 PID、到达时间和服务时间输出是每个进程的开始时间、完成时间以及平均等待时间和平均周转时间。这个“先设计输入输出再设计数据结构”的顺序比上来就写核心算法重要得多因为三种算法共用同一套 PCB 结构数据结构稳定了后面就是策略问题。FCFS 的核心代码很直接按到达时间排序后顺序执行#include stdio.h #include stdlib.h typedef struct { int pid; int arrive; /* 到达时间单位 ms */ int service; /* 服务时间单位 ms */ int start; /* 首次开始运行时间 */ int finish; /* 完成时间 */ } pcb_t; /* 按到达时间排序同时到达按 pid 升序保证输出稳定 */ static int cmp_arrive(const void *a, const void *b) { const pcb_t *x a, *y b; if (x-arrive ! y-arrive) return x-arrive - y-arrive; return x-pid - y-pid; } void fcfs(pcb_t *procs, int n) { int cur 0; /* 当前系统时间 */ for (int i 0; i n; i) { if (cur procs[i].arrive) cur procs[i].arrive; procs[i].start cur; procs[i].finish cur procs[i].service; cur procs[i].finish; printf(pid%d start%d finish%d\n, procs[i].pid, procs[i].start, procs[i].finish); } }代码逻辑不复杂cur维护的是 CPU 当前的“空闲边界”如果下一个进程到达时间晚于cur说明 CPU 有空等需要把cur跳到进程到达时间。cmp_arrive用qsort排序时保证输出稳定。这里有个参数点值得注意排序只排一次FCFS 的“先来先服务”完全由到达时间决定SJF 则要求每次从已到达的进程里选服务时间最短的不能只做一次全局排序很多同学的“SJF 实现”其实做成了全局最短作业优先而不是短作业优先调度。RR 轮转的时间片是个需要调的参数。时间片太小上下文切换开销大时间片太大算法退化回 FCFS。做课程实验时我一般用 1 个时间单位因为输入规模小能清楚看到轮转过程如果实验要求“大时间片”和“小时间片”对比可以做成命令行参数。RR 的实现要用队列结构维护就绪进程每执行一个时间片检查进程是否完成没完成就排到队尾。唯一要留意的是新到达的进程和未完成的进程谁先入队教科书和实验指导书可能给不同规则以你手里那份指导书为准。3.2 内存管理实验页面置换算法要从“手算能对”和“程序能跑”两头验证内存管理实验常见两个方向一个是动态分区分配首次适应、最佳适应另一个是页面置换FIFO、LRU、OPT。这两个方向代码都不难难点在于如何验证自己写对了。我的建议是先用纸笔跑一遍经典样例再用程序跑同一份输入两边对不上就逐行打印中间状态。以 LRU 为例算法核心是“当页框满时淘汰最久未被访问的那一页”。很多同学用“访问次数最少”代替“最久未被访问”这是错误的理解。一个简单的数组实现是给每个页框记录“上次被访问时的引用序号”序号越大表示越新淘汰时找序号最小的那一项#include stdio.h #include string.h #define FRAME_NUM 4 int main(void) { /* 经典页面访问序列也是很多教材的手算例题 */ int page[] {7, 0, 1, 2, 0, 3, 0, 4, 2, 3, 0, 3, 2, 1, 2, 0, 1, 7, 0, 1}; int n sizeof(page) / sizeof(page[0]); int frame[FRAME_NUM]; /* 页框内容 */ int last[FRAME_NUM]; /* 上次访问时的引用序号越小越“旧” */ int miss 0; memset(frame, -1, sizeof(frame)); memset(last, -1, sizeof(last)); for (int i 0; i n; i) { int hit 0; for (int j 0; j FRAME_NUM; j) { if (frame[j] page[i]) { hit 1; last[j] i; /* 命中则刷新访问时间 */ break; } } if (hit) continue; /* 缺页淘汰 last 值最小的页框 */ miss; int victim 0; for (int j 1; j FRAME_NUM; j) if (last[j] last[victim]) victim j; frame[victim] page[i]; last[victim] i; } printf(page faults %d\n, miss); return 0; }代码里两个关键点一是last数组初始化为 -1这样前几次加载页面时空页框永远是最老的新页面会被放入空页框而不是错误地淘汰某个已有页面二是命中时只更新last[j]不能改动frame内容。各种教材上 LRU 的缺页数不完全一致多半是因为“初始时页框为空”是否计入缺页的约定不同写报告时把这个前提写清楚比纠结某一串数字更重要。动态分区分配算法同理首次适应FF维护空闲分区表并按地址递增排序每次从头找第一个满足 size 的空闲块最佳适应BF则把空闲块按大小排序找最小满足块。结构体里要有起始地址、长度和状态标志分配和释放各写一个函数。验收时老师常会追问“拼接相邻空闲区”有没有实现以及分配后剩余空间是否作为新空闲块插入表这两个点比算法主流程更容易被忽略。3.3 文件系统实验用 Linux 命令验证索引节点、硬链接与软链接文件系统实验有一个“性价比”很高的做法先用 Linux 命令把概念验证一遍再去读或者补全参考代码。很多同学一上来就啃 C 代码里的 inode 结构体看得云里雾里其实用几条命令就能把索引节点的核心性质看得明明白白# 建一个测试目录 mkdir -p /tmp/os-fs cd /tmp/os-fs # 创建普通文件然后分别建立硬链接和软链接 echo hello os data.txt ln data.txt hard.txt ln -s data.txt soft.txt # -i 参数显示 inode 号hard.txt 与 data.txt 的 inode 相同 ls -li data.txt hard.txt soft.txt输出里你会看到data.txt和hard.txt的 inode 编号完全相同链接计数变成 2而soft.txt是另一个独立的 inode文件类型显示为llink。用stat命令看得更细stat data.txt hard.txt soft.txtstat会明确印出Links: 2和Inode编号。到这里书里那句“硬链接是目录项的别名软链接是新文件”就有了直观对应。接着可以做两个对抗直觉的验证删除data.txt后hard.txt仍然能读到内容因为 inode 的引用计数还没到 0soft.txt则会变成断链。这就是硬链接与软链接最本质的区别答辩时老师一问一个准。文件系统实验的 C 代码部分如果是模拟实现通常要求写 mkfs 和 mount 的简化版操作一个虚拟磁盘文件。建议把虚拟磁盘定义成固定大小比如 1MB的二进制文件用 fwrite/read 按块读写不要碰真实磁盘分区——课程实验不需要也不应该拿真实分区做实验。GB 级以上的虚拟磁盘也别做一是慢二是验证困难1MB 足够放下几十个文件目录项了。3.4 实验设计的变体单道批处理、多道并发与菜单化封装同样是这三个模块不同学年的实验指导书要求的交互形式可能不同。有的要求写成一个控制台菜单程序用户在三种调度算法之间切换有的要求从文件读入进程数据输出结果到文件。先看清楚指导书要求再决定代码组织。如果是菜单化封装一个switch分支就够了但要注意每个分支结束后要把公共数据恢复到初始状态否则第二次运行会带着上次的残留数据跑结果怎么看怎么不对。如果实验要求退化为“单道批处理”模型那进程调度部分其实没有并发只有排队代码会简单很多如果要求“多道并发”或“模拟时钟中断”就要在代码里维护一个时钟变量和就绪队列时间片轮转才能体现出来。我见过最多的翻车不是算法写错而是代码里混入了真实sleep()调用去模拟进程执行——这在验收时会把 1 秒内该跑完的实验拖成 10 秒钟而且调度顺序可能因为系统调度抖动而变得不稳定。切记这是离散事件模拟不是真实多进程调度不要引入真实时间等待。4. 从能跑代码到能交作业Makefile 统一编译、日志打点与验收自查4.1 一个 Makefile 管三个实验别让编译成为答辩翻车点三个实验的代码分散在不同目录如果每次验收前都手动敲gcc命令很容易出现“这个实验能编译、那个实验编不过”的尴尬。把编译过程写进 Makefile一次make全部搞定是这门课性价比最高的工程化动作。# 放在 os-lab 根目录 CC gcc CFLAGS -Wall -Wextra -stdc11 -g TARGET fcfs_sjf_rr all: $(TARGET) fcfs_sjf_rr: exp1_scheduler/src/scheduler.c $(CC) $(CFLAGS) -o $ $ mem_lru: exp2_memory/src/mem_lru.c $(CC) $(CFLAGS) -o $ $ clean: rm -f $(TARGET) mem_lru *.o .PHONY: all clean这里逐项说下参数为什么这么定-Wall -Wextra是打开所有常见警告代码里有未使用变量、类型不匹配都会报警而不是带着隐患闷头跑-stdc11锁定语言标准避免本机默认的 gnu17 扩展在你换到老师机器上编不过-g生成调试信息配合 gdb 排错必需。$是目标文件名$是第一个依赖文件这两个自动变量让每个编译规则不用重复写文件名。.PHONY声明all和clean是伪目标防止目录下恰好有叫clean的文件时 make 认为“已经是最新”而跳过执行。提交前养成习惯先make clean再make然后用git status确认没有遗留的.o文件。干净环境能编译比什么都重要。4.2 日志打点把调度过程打印成人能读懂的流水账程序能跑出最终结果只是及格线。答辩时最容易加分的是中间过程日志——老师需要一眼看到“这个进程什么时间开始、什么时间完成”。给每个关键事件加一行打印#include stdio.h /* 统一日志格式[时间] 事件 进程号 */ static void log_event(const char *event, int pid, int ts) { printf([%6dms] %-12s pid%d\n, ts, event, pid); }引用格式里%-12s是左对齐占 12 个字符保证不同事件名打出来整齐对齐。但只写这一句还不够有个坑几乎每届都会踩默认情况下printf是行缓冲重定向到文件时变成全缓冲程序异常退出会导致缓冲区里的日志丢失看起来像“跑到一半没输出”。解决方法是程序入口处取消缓冲int main(void) { /* 取消 stdout 缓冲保证日志立即落盘重定向不丢内容 */ setvbuf(stdout, NULL, _IONBF, 0); /* 实验逻辑... */ return 0; }_IONBF表示无缓冲每条日志立刻写出。代价是频繁打印时性能下降但对课程实验的数据量完全无所谓。日志格式尽量固定后面写脚本做回归验证、画甘特图都要靠解析这个格式。4.3 用脚本做回归验证同样的输入两次结果必须完全一致实验写到最后最怕的不是跑不出结果而是“这次和上次跑得不一样”。尤其进程调度里如果还有随机因素或者你把输入文件路径写成了相对路径换个目录跑就崩。把这些验证固化成一个脚本每次改动代码后一键回归#!/usr/bin/env bash set -euo pipefail for algo in fcfs sjf rr; do ./fcfs_sjf_rr --algo ${algo} test/input.txt out_${algo}.log diff out_${algo}.log test/expected_${algo}.log echo ${algo}: ok doneset -euo pipefail三件套的意思分别是一有命令失败就退出、变量未定义就报错、管道中任一级失败都算整体失败。diff比对输出和预期值有差异立刻告诉你。这个脚本的妙处在于它把“我觉得应该没问题”变成“机器告诉我没问题”。每次改动调度算法的核心逻辑跑一遍脚本三个算法全绿你才有底气去提交。生成expected_*.log的方法很简单自己写一个已经确认正确的小规模输入手工推演一遍结果填进去或者用当前版本跑一次人工核对输出合理后存为期望文件。记住一个原则期望文件一旦确认就不要轻易覆盖。如果实验要求改变导致输出格式变化要同时更新期望文件并在 git 提交信息里写明理由。4.4 验收自查清单提交和答辩前跑一遍这些把检查项做成一张清单贴在报告文件夹里检查项操作或判定标准常见问题干净环境可编译make clean make无报错、无警告本机能编老师机器编不过无内存错误valgrind --leak-checkfull ./程序段错误、内存泄漏输出稳定可复现回归脚本全部ok两次运行结果不一致手算与程序一致经典样例纸笔推演结果与输出相同缺页数、周转时间对不上报告截图与代码同步截图里的输出能由当前代码重新生成代码改了截图是旧的最后一行是很多人忽略的“报告与代码同步”。见过太多同学代码改了三版报告里还贴第一版的截图答辩时老师让现场跑一遍输出和报告对不上解释再多都显得不严谨。截图不嫌晚验收前最后跑一遍统一截。5. 避坑操作系统实验最容易翻车的 5 个现场5.1 Windows 拷来的代码在 Linux 下编译报错现象代码在自己 Windows 上写了一半复制进虚拟机后make报stray \r in program或者expected before ...报错行号还指向一个看起来完全没有问题的空行。原因Windows 文本文件用 CRLF\r\n换行Linux 只用 LF\n。编译器把\r当成了合法字符参与语法分析在词法层面就爆了。解决在虚拟机里跑一次换行符转换或者在 Windows 的编辑器里把换行符统一设成 LF。命令行处理用 sedsed -i s/\r$// exp1_scheduler/src/scheduler.c\r$匹配行尾的回车符-i原地写回。如果整个目录都要转换用find批量处理find . -name *.c -o -name *.h | xargs sed -i s/\r$//治本的办法是在 git 仓库根目录放一个.gitattributes文件声明* textauto eollf以后每次 clone 和 checkout 都自动转成 LF。对付这种问题规则越早定越好不要等到答辩前夜才来处理。5.2 虚拟机提示“客户机操作系统已禁用 CPU”或宿主机蓝屏重启现象用 VMware 启动实验虚拟机时弹窗提示“客户机操作系统已禁用 CPU。请关闭或重置虚拟机。”或者宿主机在虚拟机运行过程中突然蓝屏重启实验数据没保存。原因多数是宿主机 BIOS 里没有开启虚拟化技术Intel VT-x 或 AMD-V也可能是之前装过别的虚拟机软件或 Windows 沙盒和当前虚拟机占用冲突。这类问题在计算机基础不一的实验室机器上特别常见属于典型的“环境玄学”代码一行没写照样跑不了。解决重启进 BIOS开机按 Del 或 F2不同品牌键位不同找到 Intel Virtualization Technology 或 SVM Mode设为 Enabled。Windows 侧的虚拟化安全性设置也可能导致冲突可以去“Windows 功能”里关掉与 Hyper-V 相关的可选组件或者在 VMware 的设置里把“虚拟化引擎”里的“虚拟化 Intel VT-x/EPT”和“虚拟化 CPU 性能计数器”统统勾上然后重启宿主机再试。VirtualBox 用户如果遇到同样的“禁用 CPU”提示路径在 设置-系统-处理器-启用 PAE/NX 和嵌套虚拟化两个都开。5.3 输出日志错乱或丢失stdout 缓冲与 fflush 的问题现象程序运行时间不长屏幕上能看到部分输出但重定向到文件后日志少了后半段或者两条日志打印顺序跟预期相反。原因默认的 stdout 在终端上是行缓冲重定向到文件时变为全缓冲。缓冲区满或者进程正常退出时才 flush。如果程序异常崩溃或者你在代码里调用了_exit()缓冲区内容来不及写出就丢了。解决程序入口加setvbuf(stdout, NULL, _IONBF, 0)关闭缓冲或者在每条日志后手动fflush(stdout)。用fprintf(stderr, ...)打错误日志也可以stderr 默认无缓冲。关键是要理解我们做的是模拟实验不是真实系统日志完整性比“性能”重要得多别为了省一次 flush 丢掉一个关键事件。5.4 页面置换缺页数对不上内存越界导致段错误现象LRU 实验代码跑完输出缺页次数和手算结果差了十几甚至几十数据量一调大程序直接段错误崩溃。原因缺页数对不上通常是初始状态的约定不一致——空页框加载阶段是否算缺页、页框预填充的方式不同结果天然有差异。段错误则是数组越界的典型症状页面访问序列长度是 20你定义int page[20]但循环里某个边界条件下读到了page[20]甚至更后面。解决打印每一轮循环的中间状态把frame和last数组逐项输出手算对照看到底从哪一步开始分叉。边界条件重点检查两个一是缺页时victim的初始值二是命中时last数组的更新位置。排查内存问题用编译器内置的 AddressSanitizer比 valgrind 快很多# 重新编译打开内存越界和未定义行为检测 gcc -Wall -Wextra -stdc11 -g -fsanitizeaddress,undefined -o mem_lru mem_lru.c # 运行出错会精确到文件和行号 ./mem_lru跑通之后再换回普通编译选项提交因为-fsanitize的产物体积大、速度慢不适合作为最终交付物。5.5 自己机器上编译好的代码到老师机器上全是警告甚至直接报错现象在自己电脑上make clean make一条报错都没有换到老师机器上编译满屏 warning或者直接 error。最常见的是for (int i 0; ...)这种 C99 写法在默认-stdc89的编译器下报错以及用了linux等平台相关的宏或 GNU 扩展换平台直接失效。原因不同发行版默认 gcc 的语言标准不一样。Ubuntu 22.04 默认gnu17比较宽容一些实验机房还在用老的 gcc 5.x默认gnu90很多写法直接不认。另外如果你的代码用了#include iostream却用 gcc 而不是 g 编译也会报链接错误。解决Makefile 里写死-stdc11提交前用make clean make确认没有警告不要用__linux__之外的自定义平台宏C 代码就用.c后缀配合 gccC 代码就用.cpp配合 g别混。最稳妥的做法是把老师机器当作“干净环境”在虚拟机里关掉所有个人配置、重新 clone 一次代码仓库再编译一遍。能过一次干净环境答辩时就少一个变量。6. 实验收尾之后把课设改造成简历项目的三个小动作操作系统实验做完代码能跑、报告能交这只是及格。如果想让这份经历在简历和面试中有用我一般会加三个小动作成本不高但回报明显。第一个动作是给调度器加统计输出。现在代码只有开始和完成时间加上每个进程的等待时间、周转时间、带权周转时间最后输出平均值。这些指标就是操作系统的“性能报告”面试官问“这个调度器好在哪里”你能拿数字说话而不是说“感觉挺快的”。一行打印的事但整个代码立即从一个“模拟演示”变成了一个“可评估的系统”。第二个动作是把日志画成甘特图。用 Python 的 matplotlib 读out_fcfs.log按进程和时间段画色块一页图胜过十段文字描述。做法是把日志里的start和finish解析成下面这个格式import matplotlib.pyplot as plt # 解析后的列表 (pid, start, duration) events [(1, 0, 3), (2, 3, 2), (3, 5, 4)] fig, ax plt.subplots(figsize(8, 4)) for pid, start, dur in events: ax.barh(pid, dur, leftstart, height0.6) ax.set_yticks([p[0] for p in events]) ax.set_xlabel(time (ms)) plt.tight_layout() plt.savefig(gantt_fcfs.png, dpi150)这张图贴进实验报告比任何文字都直观。答辩时老师一眼看到三种算法的调度差异提问方向也会往“你分析了什么”而不是“这是不是抄的”走。第三个动作是和真实操作系统做对照。在你的进程调度模拟器跑完后去 Linux 里运行几个真实进程查看/proc/pid/stat里的utime和stime或者用time命令测量真实调度开销。做这个对照并不难但它能回答面试里那个高频问题“你学的是真实内核的调度还是模拟器里的玩具”你把模拟器和真实内核的差异讲清楚比如固定时间片和 CFS 按权重分配虚拟时间的区别就已经比大多数只背概念的候选人强了。这三个动作都不需要改核心算法属于“报告的最后一公里”。我自己的体会是当年做完这套实验就急着删了后来面试被问到 Linux 进程状态和调度器时只能对着书硬答心里其实没底。如果当时多跑一次对照实验简历和面试都会主动很多。希望这篇整理能让你把同样一份实验资源真正变成自己的东西——环境先立住核心跑通验证做够最后加一点“别人没想到”的余量就够用了。本文还有配套的精品资源点击获取
返回列表