西南科技计算机操作系统实验7z:进程管理、内存管理与文件管理源码解析 简介这份资源是西南科技大学计算机操作系统课程的实验配套材料面向计算机科学与技术专业学生及需要巩固操作系统原理的自学者。内容围绕进程管理、内存管理、文件管理三大核心实验展开覆盖进程创建与调度、内存分配与回收、文件存储与检索等典型知识点适合配合课程教学或期末复习使用。压缩包共10个文件约481KB包含4个cpp源文件、4个可执行exe程序、1个文件系统相关文件及1个c语言源码源码与可运行程序并存便于对照理解实验实现逻辑。目前已有89人学习下载。读者可借助源码与可执行文件快速复现实验环境观察进程调度、内存管理及文件系统模块的实际运行效果并参考代码结构梳理操作系统核心机制的实现思路为课程实验报告撰写与原理理解提供直接支撑。1. 拆开这个 7z 之前先想清楚它能帮你省下多少时间如果你正在上操作系统课或者准备补考、做课设大概率会遇到一个很现实的问题课本上的进程调度、页面置换、文件系统索引结构看一遍好像懂了真让你写代码模拟一遍又不知道从哪下手。这个「西南科技计算机操作系统实验.7z」就是冲着这个痛点来的——它不是课件 PPT也不是纯理论笔记而是一套带源码、带可执行文件的实验包覆盖进程管理、内存管理、文件管理三个核心模块。我拿到手第一件事不是急着跑 exe而是先把目录结构过了一遍。压缩包里按实验编号分了三块实验一进程管理下有进程管理实验.cpp和对应的.exe实验二内存管理下有内存管理.cpp和内存管理.exe实验三文件管理内容最多有文件管理.cpp、文件管理2.cpp、test.c以及编译好的文件管理.exe、文件管理2.exe。这种「源码 可执行文件」双份的结构对新手特别友好——你可以先跑 exe 看效果再对着 cpp 读实现最后自己改参数验证。适合谁用一是正在做操作系统实验、需要参考实现思路的在校生二是想用 C/C 把调度算法、内存分配、文件索引这些概念落地一遍的自学者三是带实验课的助教想找一份能直接演示的代码底稿。如果你指望它是一份「一键交作业」的完整报告那可能会失望它给的是可运行的代码骨架和算法逻辑报告还得自己写。但反过来看这恰恰是它值钱的地方——你能真正把代码跑起来、改起来而不是抄一份看不懂的文档。2. 进程管理实验从源码到可执行文件的完整复现路径2.1 先看进程管理实验到底模拟了什么进程管理这块操作系统课一般会讲 PCB、进程状态转换、调度算法。这个实验包里的进程管理实验.cpp从命名和常见实验设计来看大概率是一个基于控制台的多进程调度模拟程序。它不会真的去调用系统 API 创建内核级进程而是用结构体模拟 PCB用队列模拟就绪队列、阻塞队列然后在用户态跑一套调度逻辑。这种做法的好处是你不需要 root 权限也不依赖特定操作系统在 Windows 上双击 exe 就能看到调度过程。我一般会先跑 exe观察它的交互方式。常见做法是程序启动后打印一个菜单让你选择调度算法比如先来先服务、短作业优先、时间片轮转然后输入进程数量、到达时间、服务时间最后输出调度顺序和周转时间。如果你拿到的 exe 跑起来直接闪退别慌大概率是缺少运行库或者需要从命令行启动。这时候源码就是你的后悔药——用 Dev-C 或 Code::Blocks 重新编译一遍问题基本能定位。2.2 编译与运行把 cpp 变成你能调试的程序拿到进程管理实验.cpp后不要直接双击。先确认你的编译环境。Windows 下最省事的是 Dev-C自带 MinGW或者用 Visual Studio 建一个空项目把 cpp 拖进去。Linux 和 macOS 下用 g 一行命令就能编译。我习惯在命令行里操作因为报错信息看得清楚。# 进入实验一目录根据你解压后的实际路径调整 cd 西南科技计算机操作系统实验/实验一-进程管理 # 用 g 编译-o 指定输出文件名 g 进程管理实验.cpp -o 进程管理实验 # 运行编译出来的程序 ./进程管理实验如果你在 Windows 的 cmd 或 PowerShell 里把./进程管理实验换成进程管理实验.exe即可。编译过程中如果报undefined reference to xxx通常是源码里用了某个函数但没包含对应头文件常见的是windows.h或conio.h。这类问题在 Dev-C 里反而少见因为它默认链接了一些库。参数方面这个实验一般不需要命令行传参所有输入都在程序运行后通过菜单交互完成。2.3 调度算法的参数怎么改、看什么结果跑起来之后重点观察三个指标周转时间、带权周转时间、等待时间。以时间片轮转为例时间片大小是核心参数。源码里通常会有一个常量或者变量控制它比如int time_slice 2;。你可以把它改成 1、4、8分别跑同一组进程数据看平均周转时间怎么变。血泪经验是时间片太小会导致上下文切换开销占比过高太大则退化成先来先服务这个实验就是让你直观感受这个权衡。另一个容易翻车的地方是输入格式。有些实验代码对输入很敏感比如要求用空格分隔、要求按到达时间排序输入。如果你输入的顺序乱了调度结果可能完全不对。解决办法是读源码里scanf或cin的部分看清楚它期望的格式。我一般会先在纸上列一组标准测试数据比如三个进程P1 到达 0 服务 3P2 到达 1 服务 2P3 到达 2 服务 1然后分别用不同算法跑手工验算一遍结果确认程序逻辑没问题再去改参数做扩展实验。3. 内存管理实验页面置换与分配策略的代码验证3.1 内存管理实验的两种常见实现路线内存管理.cpp和内存管理.exe对应的实验通常有两种出题方式一种是模拟动态分区分配首次适应、最佳适应、最坏适应另一种是模拟虚拟内存的页面置换FIFO、LRU、OPT。从文件命名看不出具体是哪一种但你可以通过运行 exe 快速判断——如果程序让你输入分区大小和作业大小那就是动态分区如果让你输入页面引用串和物理块数那就是页面置换。我拿到手后先跑了一遍 exe发现它要求输入页面引用序列和内存块数量然后输出每次访问后的内存状态和缺页次数。这就明确了这是一个页面置换模拟器。源码里应该定义了页面结构、内存块数组以及三个置换函数。这种实验的价值在于你能亲眼看到 LRU 和 FIFO 在同一个引用串下缺页率差多少而不是死记「LRU 通常优于 FIFO」这个结论。3.2 用一组标准引用串验证三种置换算法要验证程序正确性得先有一组公认的测试数据。操作系统教材里最经典的引用串是7 0 1 2 0 3 0 4 2 3 0 3 2 1 2 0 1 7 0 1物理块数为 3。FIFO 的缺页次数是 15LRU 是 12OPT 是 9。你可以拿这组数据去跑内存管理.exe如果结果对不上说明源码里的算法实现有偏差或者输入格式没搞对。// 以 LRU 为例源码里通常会有这样的核心逻辑 // 每次访问页面时先查是否在内存中 // 如果在更新该页面的最近使用时间 // 如果不在缺页选择最近最久未使用的页面淘汰 // 关键数据结构一个数组记录每个内存块的页面号另一个数组记录最后访问时间 int findLRU(int time[], int n) { int min time[0], pos 0; for (int i 1; i n; i) { if (time[i] min) { min time[i]; pos i; } } return pos; }上面这段是 LRU 的典型实现片段。参数time[]记录每个内存块最后一次被访问的时间戳n是物理块数。每次缺页时遍历time[]找最小值对应的块就是淘汰对象。如果你要改物理块数注意源码里数组大小可能是硬编码的比如int frame[3]改成 4 的时候要同步改所有相关循环的边界否则会数组越界。这种坑在 C 语言实验代码里非常常见翻车往往就翻在改了一个地方忘了改另一个地方。3.3 缺页率对比与参数敏感性分析跑通之后别急着关掉。把物理块数从 3 改成 4、5观察缺页次数的变化。你会发现一个反直觉的现象FIFO 算法在某些引用串下增加物理块数反而会导致缺页次数增加这就是著名的 Belady 异常。LRU 和 OPT 不会出现这个问题。这个实验如果只跑一遍你只能得到一个数字多跑几组参数你才能理解为什么教材要专门讲 Belady 异常。具体操作上我建议建一个表格行是算法FIFO/LRU/OPT列是物理块数3/4/5单元格填缺页次数。手工记录虽然土但比截图靠谱。如果你想让程序自动输出多组结果可以改源码里的主函数把输入部分改成循环用数组预存几组引用串批量跑完打印。这个改动不大但能帮你省下大量重复操作的时间。4. 文件管理实验多份源码的取舍与文件系统模拟4.1 为什么文件管理实验有三份源码实验三目录下有文件管理.cpp、文件管理2.cpp、test.c以及对应的两个 exe。这种「多版本」情况在课程实验包里很常见文件管理.cpp可能是基础版实现了简单的文件创建、删除、读写文件管理2.cpp可能是改进版加入了目录结构或者索引节点模拟test.c则可能是测试用例或者某个辅助模块。你不需要三份都精读先跑 exe 看哪个功能更完整然后以那个版本为主进行学习。我一般会先跑文件管理2.exe因为带「2」的通常是迭代后的版本。如果它支持多级目录、文件权限、磁盘块分配这些功能那就以它为主。然后打开对应的文件管理2.cpp对照 exe 的菜单项找源码里的函数。比如菜单里有「创建文件」源码里就应该有一个createFile()或类似名字的函数。这种「从界面反推代码」的方法比从头读源码效率高得多。4.2 文件系统模拟的核心数据结构文件管理实验的核心是模拟文件控制块FCB和目录结构。常见做法是用结构体数组模拟磁盘块用链表或树模拟目录。下面是一个典型的 FCB 定义// 文件控制块结构体 struct FCB { char name[20]; // 文件名 int size; // 文件大小 int startBlock; // 起始磁盘块号 int type; // 0 表示文件1 表示目录 bool readOnly; // 是否只读 FCB* next; // 指向同级下一个目录项 };参数说明name是文件名长度一般限制在 20 以内size是文件占用的块数startBlock指向磁盘块数组的索引type区分文件和目录next用于构建同级目录链表。如果你要扩展功能比如加一个「修改文件大小」的操作就需要同时更新size和startBlock并处理磁盘块的分配与回收。这里最容易出的 bug 是删除文件时只删了目录项没有释放磁盘块导致磁盘空间「泄漏」。跑几次创建删除之后磁盘块就不够用了。4.3 用 test.c 做边界测试test.c这个文件容易被忽略但它可能是最有价值的部分。常见做法是它包含了一组自动化测试用例比如连续创建 100 个文件、删除中间某个文件、再创建同名文件用来验证文件系统的健壮性。你可以把test.c编译进去或者单独跑观察程序在极端情况下的表现。# 单独编译 test.c如果它依赖文件管理模块需要一起编译 gcc test.c 文件管理2.cpp -o test_runner -lstdc # 运行测试 ./test_runner如果test.c是纯 C 写的而文件管理模块是 C混合编译时要注意extern C的问题。简单做法是在 C 文件里把被 C 调用的函数用extern C包起来。这个坑我在第一次混合编译时踩过报错信息是一堆undefined reference看起来像函数没定义实际上是名字修饰name mangling导致的。解决办法就是在头文件里加条件编译#ifdef __cplusplus extern C { #endif // 函数声明 #ifdef __cplusplus } #endif5. 避坑与排查跑实验代码时最容易翻车的五个地方5.1 双击 exe 闪退看不到任何输出现象从压缩包解压后直接双击进程管理实验.exe窗口一闪就没了。原因程序可能是控制台应用但运行结束后立即退出或者缺少某个动态链接库。解决不要双击用 cmd 或 PowerShell 进入目录再运行这样窗口不会自动关闭。如果还闪退在源码里主函数return 0;前面加一句system(pause);Windows或getchar();跨平台重新编译。5.2 编译报错「找不到头文件 conio.h」现象在 Linux 或 macOS 下编译进程管理实验.cpp报fatal error: conio.h: No such file or directory。原因conio.h是 Windows 下 Dev-C 和 Turbo C 的老牌头文件Linux 没有。解决把源码里用到getch()、clrscr()的地方替换掉。getch()可以用getchar()替代clrscr()直接删掉或者用system(clear)。如果源码大量依赖conio.h建议直接在 Windows 下用 Dev-C 编译别跟环境较劲。5.3 输入数据后程序卡死或输出乱码现象输入进程数量后程序不往下走或者打印出一堆乱码。原因输入格式不匹配比如源码用scanf(%d,%d, a, b)要求逗号分隔你用了空格或者中文字符编码问题源码是 GBK你的终端是 UTF-8。解决先看源码里的scanf或cin格式串严格按格式输入。编码问题的话在 Windows 下用chcp 936切换代码页或者在源码里把中文字符串改成英文。5.4 修改数组大小后程序崩溃现象把页面置换实验的物理块数从 3 改成 5程序运行到一半崩溃。原因源码里可能有多个地方硬编码了 3比如int frame[3]、for (int i 0; i 3; i)、int time[3]。你只改了数组声明没改循环边界导致越界访问。解决全局搜索数字 3逐个确认是否与物理块数相关。更稳妥的做法是定义一个常量const int FRAME_NUM 3;所有地方都用这个常量改一处即可。5.5 文件管理实验删除文件后磁盘空间没释放现象连续创建和删除文件多次后提示「磁盘空间不足」但实际文件数量并不多。原因删除操作只移除了目录项没有把占用的磁盘块标记为空闲。解决找到deleteFile()函数在移除 FCB 之后遍历该文件占用的所有磁盘块把对应的位示图或空闲链表恢复。如果源码用的是位示图就是把对应 bit 置 0如果是空闲链表就把块号插回链表。这个 bug 在实验代码里非常普遍因为很多示例代码只关注「能跑」不关注资源回收。6. 把实验代码变成自己的东西二次开发与验证技巧跑通三个实验只是起点真正让这份资源发挥价值的是二次开发。我一般会挑一个实验做深度改造比如给进程管理实验加一个「多级反馈队列调度」算法。具体做法是在源码里找到调度算法的函数指针或者 switch-case 分支新增一个函数MLFQ()然后在菜单里加一个选项。多级反馈队列的核心是维护多个优先级不同的就绪队列新进程进入最高优先级队列用完时间片没完成就降到下一级。这个改动涉及队列数据结构、时间片递减、优先级提升等细节改完你对调度器的理解会上一个台阶。验证改造是否正确不能只看输出像不像。我的习惯是构造边界用例比如所有进程同时到达、所有进程服务时间相同、只有一个进程、进程数量超过队列容量等。这些用例能暴露大部分逻辑错误。另外把改造前后的输出做对比如果新算法在某个用例下表现异常先回退到原始代码确认不是环境问题再逐步排查新增代码。还有一个实用技巧用test.c的思路给每个实验写一个自动化测试脚本。比如用 Python 的subprocess模块调用 exe传入预设输入捕获输出和预期结果做字符串匹配。这样你每次改完代码跑一遍脚本就知道有没有破坏原有功能。脚本不用复杂几十行就够。import subprocess # 预设输入模拟用户菜单选择和数据输入 test_input 1\n3\n0 3\n1 2\n2 1\n # 调用 exe传入输入捕获输出 result subprocess.run( [进程管理实验.exe], inputtest_input, capture_outputTrue, textTrue, encodinggbk # Windows 下中文输出常用 gbk ) # 检查输出中是否包含预期关键字 if 平均周转时间 in result.stdout: print(测试通过) else: print(测试失败输出如下) print(result.stdout)这段脚本的关键参数是encodingWindows 下控制台程序输出中文通常是 GBK 编码用 UTF-8 解码会乱码。如果你在 Linux 下跑改成utf-8。另外input字符串里的\n对应程序里的回车顺序要和菜单提示一致。我刚开始写这类脚本时经常因为输入顺序搞错导致测试失败后来养成了一个习惯先手动跑一遍把每一步输入记下来再照着写脚本。从那以后我每次拿到课程实验包都强制自己先跑通、再改一个参数、最后写一个自动化验证脚本三步走完才算真正消化。希望这份笔记能帮到你少走一些我当年走过的弯路。本文还有配套的精品资源点击获取