操作系统实验一——进程调度
实验内容
设 计 程 序 模 拟 进 程 的 轮 转 法 调 度 过 程 。 假 设 初 始 状 态 为 : 有 n 个 进 程 处 于 就 绪 状 态 , 有 m 个 进程 处 于 阻 塞 状 态 。 采 用 轮 转 法 进 程 调 度 算 法 进 行 调 度 。 调 度 过 程 中 , 假 设 处 于 执 行 状 态 的 进 程 不 会 阻塞 , 且 每 过 t 个 时 间 片 系 统 释 放 资 源 , 唤 醒 处 于 阻 塞 队 列 队 首 的 进 程 。
程 序 要 求 如 下 :
1 ) 输 出 系 统 中 进 程 的 调 度 次 序 ;
2 ) 计 算 CPU 利 用 率 。
说明
请注意,这段程序只实现了RR算法的最简单的一种情形,但刚好满足实验一的最低要求🤣
注意:如果遇到在visual stdio编译报错,报错内容是std::至少需要c++17。请查询如何修改编译器C++编译版本
实现步骤
设置一个符合实验要求的,可以标识进程的PCB控制块
struct PCB_Type {
char name; // 进程名
int state; // 进程状态 0--阻塞 1--就绪 2--执行
int cpu_time; // 运行需要的CPU时间(需要的服务时间)
PCB_Type() : name('\0'), state(-1), cpu_time(0) {}
};
using PCB = PCB_Type;
实现一个RR类,包含必要的两个类成员
private:
//包含#include <queue>头文件
queue<PCB *> Ready_Que; // 就绪队列
queue<PCB *> Blocked_Que; // 阻塞队列
实现类成员函数,初始队列
// 初始化两个队列
inline void init_que() {
int n, m; //n--处于就绪的进程个数 m--处于阻塞的进程个数
cout << "请输入就绪进程的个数和阻塞进程的个数:";
cin >> n >> m;
for (int i = 1; i <= n; ++i) {
PCB *process = new PCB();
printf("输入就绪进程%d的进程名和要求服务时间:", i);
cin >> process->name >> process->cpu_time;
// 初始化到就绪队列
process->state = 1;
Ready_Que.push(process);
}
for (int i = 1; i <= m; ++i) {
PCB *process = new PCB();
printf("输入阻塞进程%d的进程名和要求服务时间:", i);
cin >> process->name >> process->cpu_time;
// 初始化到阻塞队列
process->state = 0;
Blocked_Que.push(process);
}
}
实现类成员函数,模拟调度
// 模拟调度
inline void dispatch() {
cout << "输入t:";
int t; //每过t个时间片 从阻塞队列中唤醒队首进程
cin >> t;
cout << "开始调度\n";
int time = 1;
while (!Ready_Que.empty() || !Blocked_Que.empty()) {
printf("时间片%d:", time);
if (Ready_Que.empty()) {
cout << "空闲一个时间片\n";
if (time % t == 0 && !Blocked_Que.empty()) {
FBTR(); // 将处于阻塞队列首进程放入就绪队列
}
} else if (!Ready_Que.empty()) {
if (time % t == 0 && !Blocked_Que.empty()) {
FBTR(); // 将处于阻塞队列首进程放入就绪队列
}
PCB *process = Ready_Que.front();
printf("进程%c调度\n", process->name);
Ready_Que.pop();
--process->cpu_time;
if (process->cpu_time == 0) {
printf("进程%c完成\n", process->name);
} else {
Ready_Que.push(process);
}
}
++time;
}
}
独立了一份把处于阻塞队列的首进程放入就绪队列的模块
把它设置为protected属性,只用于类内部调用
protected:
// 这个点被老师问到了,其实是from block to ready😊
inline void FBTR() { //将阻塞队列队首进程放入就绪队列
PCB *process = Blocked_Que.front();
process->state = 1;
Ready_Que.push(process);
Blocked_Que.pop();
}
计算CPU利用率见完整代码
完整代码
#include <iostream>
#include <queue>
#include <iomanip>
using namespace std;
void display() {
printf("******************************\n");
printf("**\t这是一个模拟RR调度算法的程序\t**\n");
printf("**\t1.初始就绪队列和阻塞队列\t**\n");
printf("**\t2.查看初始的队列情况 \t**\n");
printf("**\t3.开始模拟调度 \t**\n");
printf("**\t4.计算CPU利用率 \t**\n");
printf("******************************\n");
}
struct PCB_Type {
char name; // 进程名
int state; // 进程状态 0--阻塞 1--就绪 2--执行
int cpu_time; // 运行需要的CPU时间(需要的服务时间)
PCB_Type() : name('\0'), state(-1), cpu_time(0) {}
};
using PCB = PCB_Type;
// 基于时间片轮转调度算法(RR)
class RR {
public:
RR() = default; // 构造
~RR() = default; // 析构
// 初始化两个队列
inline void init_que() {
int n, m; //n--处于就绪的进程个数 m--处于阻塞的进程个数
cout << "请输入就绪进程的个数和阻塞进程的个数:";
cin >> n >> m;
for (int i = 1; i <= n; ++i) {
PCB *process = new PCB();
printf("输入就绪进程%d的进程名和要求服务时间:", i);
cin >> process->name >> process->cpu_time;
// 初始化到就绪队列
process->state = 1;
Ready_Que.push(process);
}
for (int i = 1; i <= m; ++i) {
PCB *process = new PCB();
printf("输入阻塞进程%d的进程名和要求服务时间:", i);
cin >> process->name >> process->cpu_time;
// 初始化到阻塞队列
process->state = 0;
Blocked_Que.push(process);
}
}
// 模拟调度
inline void dispatch() {
cout << "输入t:";
int t; //每过t个时间片 从阻塞队列中唤醒队首进程
cin >> t;
int _idle_num = 0.0; // 记录下来调度算法执行中CPU空转情况
// RR
cout << "开始调度\n";
int time = 1;
while (!Ready_Que.empty() || !Blocked_Que.empty()) {
printf("时间片%d:", time);
if (Ready_Que.empty()) {
++_idle_num;
cout << "空闲一个时间片\n";
if (time % t == 0 && !Blocked_Que.empty()) { // 将处于阻塞队列首进程放入就绪队列
FBTR();
}
} else if (!Ready_Que.empty()) {
if (time % t == 0 && !Blocked_Que.empty()) { // 将处于阻塞队列首进程放入就绪队列
FBTR();
}
PCB *process = Ready_Que.front();
printf("进程%c调度\n", process->name);
Ready_Que.pop();
--process->cpu_time;
if (process->cpu_time == 0) {
printf("进程%c完成\n", process->name);
} else {
Ready_Que.push(process);
}
}
++time;
}
this->l = _idle_num, this->All = time - 1;
}
// 查看初始的队列信息
inline void queInfo() const {
cout << "处于就绪队列的进程有:\n";
cout << "name state cpu_time\n";
queue<PCB *> R_cur = Ready_Que;
while (!R_cur.empty()) {
PCB *tmp = R_cur.front();
R_cur.pop();
cout << setw(4) << tmp->name << setw(4) << tmp->state << setw(4)
<< tmp->cpu_time << endl;
}
cout << "处于阻塞队列的进程有:\n";
cout << "name state cpu_time\n";
queue<PCB *> B_cur = Blocked_Que;
while (!B_cur.empty()) {
PCB *tmp = B_cur.front();
B_cur.pop();
cout << setw(4) << tmp->name << setw(4) << tmp->state << setw(4)
<< tmp->cpu_time << endl;
}
}
// 计算CPU利用率
inline void calculate() const {
auto res = (float) (All - l) / (float) All;
printf("CPU利用率%.2f%%\n", res * 100.0);
}
protected:
inline void FBTR() { //将阻塞队列队首进程放入就绪队列
PCB *process = Blocked_Que.front();
process->state = 1;
Ready_Que.push(process);
Blocked_Que.pop();
}
private:
queue<PCB *> Ready_Que; // 就绪队列
queue<PCB *> Blocked_Que; // 阻塞队列
int l = 0, All = 0; // 用于计算利用率
};
int main() {
RR J;
display();
int step;
cout << "输入操作指令:";
cin >> step;
while (step != 0) {
switch (step) {
case 1:
J.init_que();
cout << "初始完成!\n";
break;
case 2:
J.queInfo();
break;
case 3:
J.dispatch();
break;
case 4:
J.calculate();
break;
default:
break;
}
cout << "输入操作指令:";
cin >> step;
}
return 0;
}
至此,实验一已经完成。