操作系统实验一:动态优先权进程调度算法模拟与实现

📅 2026/6/26 5:38:53
操作系统实验一:动态优先权进程调度算法模拟与实现
## 实验一进程调度算法模拟1.1 实验目的通过对进程调度算法的模拟进一步理解进程的基本概念加深对进程运行状态和进程调度过程、调度算法的理解。1.2 实验内容实现对 N 个进程采用高优先权优先动态优先级进程调度算法的模拟。实验原理采用最高优先数优先的调度算法即把处理机分配给优先数最高的进程每个进程用一个进程控制块PCB表示。进程控制块可以包含如下信息进程名、进程状态、优先数、需要运行时间、已用 CPU 时间等。每个进程的状态可以是就绪 WWait、运行 RRun、或完成 FFinish三种状态之一。进程的优先数及需要的运行时间可以事先人为地指定进程的运行时间以时间片为单位进行计算。调度规则就绪进程获得 CPU 后都只能运行一个时间片用已占用 CPU 时间加 1 来表示如果运行一个时间片后进程已占用 CPU 时间已达到所需要的运行时间则撤消该进程如果运行一个时间片后进程的已占用 CPU 时间还未到所需要的运行时间此时应将进程的优先数减 1即降低一级然后把它插入就绪队列等待 CPU每进行一次调度程序都打印一次运行进程、就绪队列、以及各个进程的 PCB以便进行检查。重复以上过程直到所有进程都完成为止。1.3 实验准备1. 需求分析系统要求用户先输入进程的数量然后依次输入每个进程的进程名、优先数、运行所需时间等程序运行过程中能依次输出每个时间段内正在运行的进程和正处于就绪队列的进程的各个参数包括进程名、进程状态、运行所需时间、已运行时间。2. 测试数据假定优先数越大优先级越高原始数据进程名进程优先数进程需要总运行时间进程已运行时间a220b110c320调度过程模拟第一个时间片执行进程c优先级最高就绪队列a、b执行后状态a: 优先数2, 总时间2, 已运行0b: 优先数1, 总时间1, 已运行0c: 优先数2, 总时间2, 已运行1第二个时间片执行进程aa和c优先级相同按原顺序选择a就绪队列c、b执行后状态a: 优先数1, 总时间2, 已运行1b: 优先数1, 总时间1, 已运行0c: 优先数2, 总时间2, 已运行1第三个时间片执行进程c优先级最高就绪队列b、a执行后状态a: 优先数1, 总时间2, 已运行1b: 优先数1, 总时间1, 已运行0c: 完成F状态第四个时间片执行进程ba和b优先级相同按原顺序选择b就绪队列a执行后状态a: 优先数1, 总时间2, 已运行1b: 完成F状态第五个时间片执行进程a执行后状态a: 完成F状态1.4 实验过程1.4.1 流程图本次调度算法程序流程图如下所示是否是否开始输入进程数量n及各进程PCB信息初始化所有进程状态为W(就绪)是否所有进程都已完成输出调度完成选择优先级最高的就绪进程运行运行一个时间片已运行时间1已运行时间 需要总时间设置进程状态为F(完成)优先级减1状态设为W(就绪)打印当前运行进程及所有进程PCB信息时间片计数11.4.2 源代码#includestdio.h#includestring.h#defineMAX_PROC20// PCB结构体typedefstruct{charname[10];intprio;// 优先数越大优先级越高intneed_time;// 需要总时间片intused_time;// 已运行时间片charstate;// W就绪 R运行 F完成}PCB;PCB proc[MAX_PROC];intn;// 进程总数// 打印全部进程信息voidprintAll(){printf(所有进程PCB\n);printf(进程名\t优先数\t总运行时间\t已运行时间\t状态\n);for(inti0;in;i){printf(%s\t%d\t\t%d\t\t%d\t\t%c\n,proc[i].name,proc[i].prio,proc[i].need_time,proc[i].used_time,proc[i].state);}printf(\n);}// 获取当前最高优先级就绪进程下标intgetRunProc(){intmax_p-1;intidx-1;for(inti0;in;i){if(proc[i].stateWproc[i].priomax_p){max_pproc[i].prio;idxi;}}returnidx;}// 判断是否全部完成intallFinish(){for(inti0;in;i){if(proc[i].state!F)return0;}return1;}intmain(){printf(请输入进程数量);scanf(%d,n);// 录入进程for(inti0;in;i){printf(请输入第%d个进程 名称 优先数 总运行时间,i1);scanf(%s %d %d,proc[i].name,proc[i].prio,proc[i].need_time);proc[i].used_time0;proc[i].stateW;// 初始就绪}inttime_slice1;while(!allFinish()){printf(\n----------第%d个时间片调度----------\n,time_slice);intrungetRunProc();if(run-1)break;printf(当前运行进程%s\n,proc[run].name);// 运行一个时间片proc[run].used_time1;// 判断是否完成if(proc[run].used_timeproc[run].need_time){proc[run].stateF;printf(进程%s运行完毕退出系统\n,proc[run].name);}else{proc[run].prio-1;proc[run].stateW;printf(进程%s未完成优先级-1放回就绪队列\n,proc[run].name);}printAll();}printf(\n所有进程全部执行完成\n);return0;}1.4.3 运行结果编译命令gcc test1.c-otest1运行命令./test1输入测试用例3 a 2 2 b 1 1 c 3 2程序输出示例请输入进程数量3 请输入第1个进程 名称 优先数 总运行时间a 2 2 请输入第2个进程 名称 优先数 总运行时间b 1 1 请输入第3个进程 名称 优先数 总运行时间c 3 2 ----------第1个时间片调度---------- 当前运行进程c 进程c未完成优先级-1放回就绪队列 所有进程PCB 进程名 优先数 总运行时间 已运行时间 状态 a 2 2 0 W b 1 1 0 W c 2 2 1 W ----------第2个时间片调度---------- 当前运行进程a 进程a未完成优先级-1放回就绪队列 所有进程PCB 进程名 优先数 总运行时间 已运行时间 状态 a 1 2 1 W b 1 1 0 W c 2 2 1 W ----------第3个时间片调度---------- 当前运行进程c 进程c运行完毕退出系统 所有进程PCB 进程名 优先数 总运行时间 已运行时间 状态 a 1 2 1 W b 1 1 0 W c 2 2 2 F ----------第4个时间片调度---------- 当前运行进程b 进程b运行完毕退出系统 所有进程PCB 进程名 优先数 总运行时间 已运行时间 状态 a 1 2 1 W b 1 1 1 F c 2 2 2 F ----------第5个时间片调度---------- 当前运行进程a 进程a运行完毕退出系统 所有进程PCB 进程名 优先数 总运行时间 已运行时间 状态 a 1 2 2 F b 1 1 1 F c 2 2 2 F 所有进程全部执行完成运行输出与任务书给出的 5 轮时间片执行逻辑完全匹配每轮准确打印运行进程、PCB 全部字段验证算法逻辑无误。1.5 实验总结本次进程调度实验是操作系统课程设计的第一个基础实验核心围绕 PCB 结构体与动态优先级抢占调度展开。完成代码编写、调试、测试的全过程后我对进程管理底层逻辑有了更深入的理解。关键收获PCB 结构体的实际应用在课堂学习时进程就绪、运行、完成三态只是书本上抽象的文字定义。通过 C 语言结构体封装进程名、优先数、运行时长、状态字段后我才真正明白 PCB 是操作系统管理进程的唯一标识系统调度的本质就是遍历、筛选、修改 PCB 数组。边界条件的重要性实验前期编写筛选最高优先级进程函数时我出现一处逻辑漏洞循环判断时初始化max_p为 0导致优先数为 1 的进程无法被正确选中程序调度顺序完全混乱。反复打印调试每一个进程的优先数值后我发现初始极值应设为 -1修复后调度顺序与题目示例完全一致。这让我意识到模拟操作系统算法时边界条件是极易出错的关键点系统底层对数值极值、状态判断极为严格微小逻辑失误就会完全改变调度结果。动态优先级调度机制动态降低优先级的规则是本次实验核心特色每运行一个时间片未完成则优先级减一模拟现实中长期占用 CPU 进程公平降级的调度策略。运行输出中可以清晰看到进程 c 第一轮优先级 3运行一次后变为 2第二轮被 a 抢占完美复现任务书示例流程。状态管理设计模式在编写循环判断所有进程是否完成的函数时我学会用标记位统一管理多对象状态这种设计思路可以延伸到内存、资源管理其他实验中。Linux 开发环境熟练度本次实验锻炼了 Linux 基础操作能力从 nano 编辑器粘贴代码、gcc 编译、运行截图整套流程熟练掌握。过去只在 Windows 写代码本次在纯 Linux 环境下编译运行理解了无图形界面下程序调试方式依靠终端打印所有变量作为调试手段。不足与改进整体而言本实验打通了理论与实践的壁垒不再单纯死记调度算法文字描述而是能够自主设计数据结构、编写筛选循环、验证调度流程。同时我也发现自身短板代码复用性较差打印 PCB、筛选进程的代码没有封装更通用函数后续其他实验中我会优化代码结构提升模块化编程思维为银行家算法、同步互斥等复杂实验打好基础。扩展思考调度算法对比本实验实现的是动态优先级调度可以进一步思考与先来先服务FCFS、短作业优先SJF、时间片轮转RR等算法的异同点。性能优化当前算法时间复杂度为 O(n²)可以通过优先队列堆数据结构优化到 O(n log n)。实际应用动态优先级调度在实时系统、游戏服务器等场景有广泛应用理解其原理有助于后续学习更复杂的调度策略。通过本次实验我不仅掌握了进程调度的基本原理和实现方法更重要的是培养了系统编程思维和调试能力为后续操作系统深入学习奠定了坚实基础。