操作系统实验一
实验一:进程调度模拟算法
一、实验目的
通过编写模拟进程调度程序,加深对进程控制块(PCB)、进程队列等概念的理解,掌握优先级调度算法和时间片轮转算法的实现方法,并体会它们在操作系统中的实际应用。
二、实验要求
1.设计进程控制块的结构,包含进程名、优先级、CPU时间、剩余时间、状态等信息。
2.实现优先级调度算法和轮转调度算法。
3.输出每次调度后各进程的状态及相关信息。
三、实验过程
1.准备
A. 查阅相关资料:
B. 初步编写程序:
C. 准备测试数据:
D. …….
2.上机调试
A.在Visual Studio和GCC编译器中进行调试,逐步排除错误并完善代码逻辑。
B.测试了不同数量和属性的进程,确保输出符合预期。
3. 主要流程和源代码
程序流程如下:
1.定义 PCB 结构;
2.实现插入函数,按优先级或轮转顺序插入;
3.实现优先级调度算法;
4.实现时间片轮转调度算法;
5.主程序中获取用户输入并调用相应的调度算法。
源代码:
#include <iostream>
#include <iomanip>
#include <vector>
#include <algorithm>
using namespace std;
// 进程状态枚举
enum State { RUN_STATE, READY_STATE, FINISH_STATE };
// 进程控制块结构
struct PCB {
string name; // 进程名
int priority; // 优先数
int cputime; // 已占用CPU时间
int needtime; // 还需时间
State state; // 进程状态
PCB* next; // 链指针
PCB(string n, int nt) : name(n), needtime(nt), cputime(0), state(READY_STATE), next(NULL) {
priority = 50 - needtime; // 初始优先数
}
};
// 全局指针
PCB* RUN = NULL; // 当前运行进程
PCB* READY = NULL; // 就绪队列头
PCB* TAIL = NULL; // 就绪队列尾
PCB* FINISH = NULL; // 完成队列头
// 打印进程信息
void PRINT() {
cout << left << setw(10) << "name"
<< setw(10) << "cputime"
<< setw(10) << "needtime"
<< setw(10) << "priority"
<< setw(10) << "state" << endl;
// 先打印运行态进程
if (RUN) {
cout << left << setw(10) << RUN->name
<< setw(10) << RUN->cputime
<< setw(10) << RUN->needtime
<< setw(10) << RUN->priority
<< setw(10) << "R" << endl;
}
// 打印就绪态进程
PCB* p = READY;
while (p) {
cout << left << setw(10) << p->name
<< setw(10) << p->cputime
<< setw(10) << p->needtime
<< setw(10) << p->priority
<< setw(10) << "W" << endl;
p = p->next;
}
// 打印完成态进程
p = FINISH;
while (p) {
cout << left << setw(10) << p->name
<< setw(10) << p->cputime
<< setw(10) << p->needtime
<< setw(10) << p->priority
<< setw(10) << "F" << endl;
p = p->next;
}
cout << "----------------------------------" << endl;
}
// 优先数算法插入就绪队列
void INSERT1(PCB* process) {
if (!READY) {
READY = TAIL = process;
return;
}
PCB *prev = NULL, *curr = READY;
while (curr && curr->priority >= process->priority) {
prev = curr;
curr = curr->next;
}
if (!prev) {
process->next = READY;
READY = process;
} else {
prev->next = process;
process->next = curr;
if (!curr) TAIL = process;
}
}
// 轮转法插入就绪队列尾
void INSERT2(PCB* process) {
if (!READY) {
READY = TAIL = process;
} else {
TAIL->next = process;
TAIL = process;
}
process->next = NULL;
}
// 从就绪队列首部取出进程
PCB* FIRSTIN() {
if (!READY) return NULL;
PCB* p = READY;
READY = READY->next;
if (!READY) TAIL = NULL;
p->next = NULL;
return p;
}
// 创建进程并插入就绪队列
void CREATE(int alg) {
string name;
int needtime;
cout << "输入进程名和需要的时间片: ";
cin >> name >> needtime;
PCB* p = new PCB(name, needtime);
if (alg == 1) INSERT1(p);
else INSERT2(p);
}
// 将进程加入完成队列
void addToFinish(PCB* p) {
p->state = FINISH_STATE;
p->next = FINISH;
FINISH = p;
}
// 优先数调度算法
void PRISCH() {
RUN = FIRSTIN();
if (!RUN) return;
RUN->state = RUN_STATE;
cout << "运行进程: " << RUN->name << endl;
// 执行一个时间片
RUN->cputime++;
RUN->needtime--;
RUN->priority--;
if (RUN->needtime <= 0) {
cout << RUN->name << " 完成!" << endl;
addToFinish(RUN);
} else {
RUN->state = READY_STATE;
INSERT1(RUN);
}
RUN = NULL;
}
// 时间片轮转调度算法
void ROUNDSCH() {
RUN = FIRSTIN();
if (!RUN) return;
RUN->state = RUN_STATE;
cout << "运行进程: " << RUN->name << endl;
// 执行一个时间片单位(2个时间片)
int slice = min(2, RUN->needtime);
RUN->cputime += slice;
RUN->needtime -= slice;
if (RUN->needtime <= 0) {
cout << RUN->name << " 完成!" << endl;
addToFinish(RUN);
} else {
RUN->state = READY_STATE;
INSERT2(RUN);
}
RUN = NULL;
}
// 释放内存
void cleanup() {
PCB* p = FINISH;
while (p) {
PCB* temp = p;
p = p->next;
delete temp;
}
}
int main() {
int alg, count;
cout << "选择调度算法 (1:优先数 2:时间片轮转): ";
cin >> alg;
cout << "输入进程数量: ";
cin >> count;
// 创建进程
for (int i = 0; i < count; i++) {
CREATE(alg);
}
// 执行调度
while (READY) {
if (alg == 1) PRISCH();
else ROUNDSCH();
PRINT();
}
cleanup();
return 0;
}
4.遇到的主要问题和解决方法
A. :进程状态更新错误。
解决:检查状态转换逻辑,确保每次调度后正确更新PCB的state字段。
B. :队列插入顺序混乱。
解决:在INSERT1和INSERT2函数中严格按优先级或轮转规则排序。
四、实验结果
五、实验总结
通过本次进程调度模拟算法实验,我对操作系统中进程管理的核心机制有了更深刻的理解与实践体会。在实验过程中,从设计进程控制块(PCB)结构到实现优先级调度算法和时间片轮转算法,每个环节都让我将理论知识与编程实践紧密结合。
在编程实践上,本次实验极大地提升了我的代码设计与调试能力。在实现插入函数时,需要根据不同算法规则调整进程在就绪队列中的插入顺序,这锻炼了我对数据结构(链表)的灵活运用能力。在调试过程中,针对进程状态更新错误和队列插入顺序混乱等问题,通过逐步排查代码逻辑、添加调试输出语句,最终成功解决问题,这让我掌握了高效的调试技巧,也培养了严谨的编程思维。
从实验收获来看,我不仅掌握了两种经典进程调度算法的实现方法,更体会到操作系统底层设计的复杂性与精妙之处。同时,实验过程也让我意识到团队协作与技术交流的重要性,通过与同学讨论问题、分享解决方案,拓宽了自己的思路。