一、实验目的
多道程序系统中,当就绪进程数大于处理机数时,须按照某种策略决定哪些进程优先占用处理机。本实验模拟实现进程调度,以加深对进程概念和不同进程调度算法的理解。
二、实验环境
1.PC微机。
2.Windows 操作系统。
3.C/C++/VB等开发集成环境。
三、实验内容与步骤
编程实现如下进程调度算法:
1)时间片轮转调度算法:时间片长度在运行时可从键盘输入。
2)多级反馈队列调度算法:至少要有三个队列,第i+1队列进程运行的时间片是第i队列的2倍。
3)高响应比优先调度算法:当调度响应比高的进程运行时,仍然是运行一个时间片,而不是完全结束,刚运行的进程,其以前的等待时间清零。
实现提示:
(1) PCB数据结构(参考)
PCB 至少包括:进程标识符、进程名、到达时间、服务时间、等待时间、完成时间、响应比等(可根据不同的算法增减)。假设多个 PCB 利用链接方式进行组织。
(2) 主要功能模块 (参考)
●进程初始化;
●显示初始化后进程的基本信息;
●时间片轮转调度算法;
●多级反馈队列调度算法;
●高响应比优先调度算法;
输入要求:可将进程初始化信息事先存入文件中,程序运行从文件中读取信息,避免从键盘输入速度慢且易出错。
输出要求:每种调度算法每次调度后应直观显示,进程调度的依据、各进程的各项参数。每种调度算法运行结束后,输出各个进程对应的完成时间、周转时间和带权周转时间,以及整体的平均带权周转时间。
四、实验结果与分析
(1)程序的框架说明
(2)各调度算法的设计思想
1、时间片轮转算法
该算法采取了非常公平的方式,即让就绪队列上的每个进程每次仅运行一个时间片。如果就绪队列上有N个进程,则每个进程每次大约都可获得1/N的处理机时间。时间片的大小对于系统性能有很大的影响。若选择很小的时间片,将有利于短作业,但意味着会频繁地执行进程调度和进程上下文的切换,这无疑会增加系统的开销。反之,若时间片选择得太长,且为使每个进程都能在一个时间片内完成,RR算法便退化为FCFS算法,无法满足短作业和交互式用户的需求。进程的切换时机体现出RR算法的特点。若一个进程在时间片还没结束时就已完成,此时立即激活调度程序,将它从执行队列中删除。若一个进程在时间片结束时还未运行完毕,则调度程序将把它送往就绪队列的末尾,等待下一次执行。
2、多级反馈队列调度算法
1、进程在进入待调度的队列等待时,首先进入优先级最高的Q1等待。
2、首先调度优先级高的队列中的进程。若高优先级中队列中已没有调度的进程,则调度次
优先级队列中的进程。例如:Q1,Q2,Q3三个队列,只有在Q1中没有进程等待时才去调度Q2,同理,只有Q1,Q2都为空时才会去调度Q3。
3、对于同一个队列中的各个进程,按照时间片轮转法调度。比如Q1队列的时间片为N,那么Q1中的作业在经历了N个时间片后若还没有完成,则进入Q2队列等待,若Q2的时间片用完后作业还不能完成,一直进入下一级队列,直至完成。
4、在低优先级的队列中的进程在运行时,又有新到达的作业,那么在运行完这个时间片后,CPU马上分配给新到达的作业(抢占式)。
3、高响应比优先调度算法
一种动态优先调度算法,它以相应比作为作业或进程的动态优先权,其目的是既照顾短作业,又考虑到作业的等待时间,使长作业不会长期等待;但每次调度前,都要进行响应比计算,会增加系统开销。
(3)实验结果
1.RR算法
2、HRN算法
3、多级反馈队列调度算法
(4)实验源程序
#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
#include <string>
using namespace std;
class JCB {
public:
int id;//进程标识符
string name;//进程名
int arriveTime;//到达时间
int rveTime;//要求服务时间
int waitTime;//等待时间,只用于最高响应比优先调度算法中
int finshTime;//完成时间
int roundTime;//周转时间
double clock = 0;//记录该进程真实服务时间已经用时的时长,用于在时间轮转调度算法中比较当前进程能否在当前时间片执行完毕
double weightingRoundTime;//带权周转时间
JCB() {}
JCB(string name, int arriveTime, int rveTime, double priority) {
this->name = name;
this->arriveTime = arriveTime;
this->rveTime = rveTime;
this->waitTime = 0;//初始等待时间置0
}
void printInf() {
cout << "进程名:" << name << ";到达时间:" << arriveTime << ";要求服务时间:"<<rveTime << ";剩余服务时间:" << ((rveTime - clock) < 0 ? 0 : (rveTime - clock)) << endl;
}
};
//按照到达时间升序
bool cmp_arrvieTime_ascend(JCB j1, JCB j2) {
return j1.arriveTime < j2.arriveTime;
}
//用于高响应比优先调度算法
bool cmp_weightingRoundTime_descend(JCB j1, JCB j2) {
return j1.weightingRoundTime > j2.weightingRoundTime;
}
//作业调度基础类
class JobScheduling {
public:
vector<JCB> process;// 存放所有进程
JCB nowPro;// 当前应执行进程
int k = 0;// process中的进程遍历时的下标
int nowTime = 0;// 当前时间
void printProcess() {
double aveRoundTime = 0;
cout << "*****************************************************" << endl;
cout << "进程名 到达时间 服务时间 完成时间 周转时间 带权周转时间" << endl;
for (int i = 0; i < process.size(); ++i) {
aveRoundTime += process[i].weightingRoundTime;
cout <<
process[i].name << " " <<
process[i].arriveTime << " " <<
process[i].rveTime << " " <<
process[i].finshTime << " " <<
process[i].roundTime<<" "<<
process[i].weightingRoundTime << endl;
}
cout << "平均带权周转时间:" << aveRoundTime / process.size()<<endl;
process.clear();
cout << "*****************************************************" << endl;
}
};
//时间片轮转调度算法
class RR :public JobScheduling {
public:
queue<JCB> RRQueue;// 就绪队列
double sliceTime;
RR(vector<JCB>jcb,double sliceTime) {
this->process = jcb;
this->sliceTime = sliceTime;
//初始对所有进程按到达时间进行排序
sort(process.begin(), d(), cmp_arrvieTime_ascend);
}
void run() {
cout << "执行时间片轮转调度算法" << endl;
Enqueue();
while (!pty() || k < process.size()) {