进程调度算法实验报告
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
一、实验目的
多道程序系统中,当就绪进程数大于处理机数时,须按照某种策略决定哪些进程优先占用处理机。
本实验模拟实现进程调度,以加深对进程概念和不同进程调度算法的理解。
二、实验环境
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 serveTime;//要求服务时间
int waitTime;//等待时间,只用于最高响应比优先调度算法中
int finshTime;//完成时间
int roundTime;//周转时间
double clock = 0;//记录该进程真实服务时间已经用时的时长,用于在时间轮转调度算法中比较当前进程能否在当前时间片执行完毕
double weightingRoundTime;//带权周转时间
JCB() {}
JCB(string name, int arriveTime, int serveTime, double priority) {
this->name =name;
this->arriveTime = arriveTime;
this->serveTime = serveTime;
this->waitTime = 0;//初始等待时间置0
}
void printInf() {
cout <<"进程名:"<< name <<";到达时间:"<< arriveTime <<";要求服务时间:"<<serveTime <<";剩余服务时间:"<< ((serveTime - clock) < 0 ? 0 : (serveTime - 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].serveTime <<" "<<
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(), process.end(), cmp_arrvieTime_ascend);
}
void run() {
cout <<"执行时间片轮转调度算法"<< endl;
Enqueue();
while (!RRQueue.empty() || k < process.size()) {
Dequeue();//出队,因为如果时间片结束当前进程未执行完又到达了新的进程,需要让刚到达的进程先进队列,再让当前进程进队列,所以进队操作写在这个函数里了}
//输出进程运行信息
printProcess();
}
void Enqueue() {//进程进入就绪队列
while (k < process.size()) {//当遍历完jcb中的所有进程时结束
if (process[k].arriveTime <= nowTime) {//已经到达的进程按到达时间先后进入队列
process[k].id = k;
cout <<"进程"<< process[k].name <<"进入就绪队列内等待"<< endl;
RRQueue.push(process[k]);
k++;
}
else {
break;//如果该进程还未到达,结束遍历。
}
}
}
void Dequeue() {
nowTime += sliceTime;//更新当前时间
//如果就绪队列不为空
if (!RRQueue.empty()) {
nowPro = RRQueue.front();//获取队首元素
RRQueue.pop();//移除队列的队首元素
nowPro.clock += sliceTime;//更新当前进程的实际服务时间
cout <<"当前时间为:"<< nowTime << endl;
cout<<"执行:";
nowPro.printInf();
//如果这个时间片时间片尚未用完,当前进程执行完毕。
if (nowPro.clock >= nowPro.serveTime) {
nowPro.finshTime = nowTime;//计算该进程完成时间
nowPro.roundTime = nowPro.finshTime - nowPro.arriveTime;//计算周转时间
nowPro.weightingRoundTime = nowPro.roundTime / nowPro.serveTime;//计算带权周转
process[nowPro.id]= nowPro;//更新jcb中的进程信息
}
else {//当前进程未运行完
Enqueue();//已到达的进程先入队
RRQueue.push(nowPro);//上一轮出的再紧接着进入队尾
}
}
else {//如果就绪队列为空,则执行入队
Enqueue();
}
}
};
class HRN :public JobScheduling {
public:
vector<JCB> HRNQueue;// 就绪队列
HRN(vector<JCB> jcb) {
process =jcb;
//初始化带权轮转时间为1
for (int i = 0; i < process.size(); i++) {
process[i].weightingRoundTime = 1;
}
//按到达时间升序排序
sort(process.begin(), process.end(), cmp_arrvieTime_ascend);
}
void run() {//最高响应比优先调度算法
nowTime = process[0].arriveTime;
Enqueue();
cout <<"最高响应比优先调度算法"<< endl;
while (!HRNQueue.empty()||k<process.size()) {
//如果将要执行的进程执行完毕之前,下一个进程都不会到来
if (k == process.size() || nowTime + (HRNQueue[0].serveTime - HRNQueue[0].clock) < process[k].arriveTime) {
Dequeue();//出队
}
//下一个进程执行到一半,会出现被新到来的进程抢占的可能
else {
int time = process[k].arriveTime - nowTime;
Dequeue(time);
Enqueue();//已到达的进程入队
}
sort(HRNQueue.begin(),HRNQueue.end(),cmp_weightingRoundTime_descend);//队列中的进程按响应比进行排序
}
printProcess();
}
void Enqueue() {//进程入队,可一次进多个
while (k < process.size()) {//当遍历完jcb中的所有进程时结束
if (process[k].arriveTime <= nowTime) {//已经到达的进程按到达时间先后进入队列
process[k].id = k;
cout <<"进程"<< process[k].name <<"进入就绪队列内等待"<< endl;
HRNQueue.push_back(process[k]);
k++;
}
else {
break;//如果该进程还未入队,即先结束遍历,保留当前下标k值,注意:此处不要k--;
}
}
}
void Dequeue() {
if (!HRNQueue.empty()) {
nowPro = HRNQueue[0];//移除队列的队首元素并且返回该对象元素
HRNQueue.erase(HRNQueue.begin());
//nowProess.beginTime = nowTime;//计算开始时间,即为上一个进程的结束时间
nowPro.finshTime = nowTime + nowPro.serveTime;//计算结束时间,该进程开始时间+服务时间
nowPro.roundTime = nowPro.finshTime - nowPro.arriveTime;//计算周转时间
nowPro.weightingRoundTime = nowPro.roundTime / nowPro.serveTime;//计算带权周转时间
nowTime = nowPro.finshTime;//获得结束时间,即当前时间,方便判断剩下的进程是否已到达
nowPro.clock = nowPro.serveTime;
cout <<"当前时间为:"<< nowTime << endl;
cout <<"执行:";
nowPro.printInf();
process[nowPro.id]= nowPro;
for (int i = 0; i < HRNQueue.size(); ++i) {
HRNQueue[i].waitTime += nowPro.serveTime;//所有进入等待队列的进程等待时间+1
HRNQueue[i].weightingRoundTime = (HRNQueue[i].waitTime +
HRNQueue[i].serveTime) / (double)HRNQueue[i].serveTime;
}
}
}
void Dequeue(int time) {
if (!HRNQueue.empty()) {
nowPro = HRNQueue[0];//该进程不会执行完毕,无需移除
nowPro.clock += time;
cout <<"当前时间为:"<< nowTime << endl;
cout <<"执行:";
nowPro.printInf();
nowTime += time;
process[nowPro.id]= nowPro;
for (int i = 0; i < HRNQueue.size(); ++i) {
HRNQueue[i].waitTime += time;//所有进入等待队列的进程等待时间+1
HRNQueue[i].weightingRoundTime = (HRNQueue[i].waitTime +
HRNQueue[i].serveTime) / (double)HRNQueue[i].serveTime;
}
}
}
};
class MFQ :public JobScheduling {
public:
queue<JCB> queue[3];
double sliceTime[3];
int sign;
MFQ(vector<JCB> jcb, double sliceTime) {
this->sliceTime[0] = sliceTime;
this->sliceTime[1] = this->sliceTime[0] * 2;
this->sliceTime[2] = this->sliceTime[1] * 2;
process =jcb;
sort(process.begin(), process.end(), cmp_arrvieTime_ascend);
}
void run() {
nowTime = process[0].arriveTime;
Enqueue(0);
cout <<"多级反馈队列调度算法"<< endl;
while (k < process.size()) {
Enqueue(0);
process[k].id = k;
while (!queue[0].empty()) {
int time = queue[0].front().serveTime - queue[0].front().clock;
//如果下一个要执行的进程,会把当前队列的时间片用完
sign = 0;
if (time >= sliceTime[0]) {
//cout << 0 << endl;
Dequeue(sliceTime[0]);
}
else {
//cout << 1 << endl;
Dequeue();
}
Enqueue(0);
}
while (!queue[1].empty()) {
//cout << 1 << endl;
int time = queue[1].front().serveTime - queue[1].front().clock;
//如果下一个要执行的进程,会把当前队列的时间片用完
sign = 1;
if (time >= sliceTime[1]) {
Dequeue(sliceTime[1]);
}
else {
Dequeue();
}
Enqueue(0);
if (queue[0].size() > 0)break;//如果第一级队列中新到来了进程
}
//到最后一个队列,直接实行FCFS
while (!queue[2].empty()) {
//cout << 2 << endl;
sign = 2;
Dequeue();
Enqueue(0);
if (queue[0].size() > 0)break;//如果第一级队列中新到来了进程
}
}
printProcess();
}
void Enqueue(int sign) {//进程入队,可一次进多个
while (k < process.size()) {//当遍历完jcb中的所有进程时结束
if (process[k].arriveTime <= nowTime) {//已经到达的进程按到达时间先后进入队列
process[k].id = k;
cout <<"进程"<< process[k].name <<"进入就绪队列内等待"<< endl;
queue[sign].push(process[k]);
k++;
}
else {
break;//如果该进程还未入队,即先结束遍历,保留当前下标k值,注意:此处不要k--;
}
}
}
void Dequeue() {
if (!queue[sign].empty()) {
nowPro = queue[sign].front();//移除队列的队首元素并且返回该对象元素
queue[sign].pop();
//nowProess.beginTime = nowTime;//计算开始时间,即为上一个进程的结束时间
nowPro.finshTime = nowTime + nowPro.serveTime;//计算结束时间,该进程开始时间+服务时间
nowPro.roundTime = nowPro.finshTime - nowPro.arriveTime;//计算周转时间
nowPro.weightingRoundTime = nowPro.roundTime / nowPro.serveTime;//计算带权周转时间
nowTime = nowPro.finshTime;//获得结束时间,即当前时间,方便判断剩下的进程是否已到达
nowPro.clock = nowPro.serveTime;
cout <<"当前时间为:"<< nowTime << endl;
cout <<"执行:";
nowPro.printInf();
process[nowPro.id]= nowPro;
}
else {
nowTime++;
}
}
void Dequeue(int time) {
if (!queue[sign].empty()) {
nowPro = queue[sign].front();//该进程不会执行完毕,无需移除
queue[sign].pop();
nowPro.clock += time;
cout <<"当前时间为:"<< nowTime << endl;
cout <<"执行:";
nowPro.printInf();
nowTime += time;
queue[sign + 1].push(nowPro);
process[nowPro.id]= nowPro;
}
else {
nowTime++;
}
}
};
int main() {
vector<JCB>jcb;
/*--------------进程初始化----------------*/
JCB p1("P1", 10, 4, 3), p2("P2", 2, 5, 2), p3("P3", 8, 5, 3), p4("P4", 13, 2, 1), p5("P5", 4, 7, 5);
jcb.push_back(p1); jcb.push_back(p2); jcb.push_back(p3); jcb.push_back(p4);
jcb.push_back(p5);
/*-----------------------------------------*/
cout <<"请输入以下数字(1:时间片轮转调度算法;2:高响应比优先调度算法;3:多级反馈队列调度算法;0:退出)"<< endl;
int k;
while(cin >>k) {
if (k == 0)break;
if (k == 1) {
double slictTime;
cout <<"请输入时间片的大小:";
cin >> slictTime;
RR rr(jcb, slictTime);
rr.run();
}
else if (k == 2) {
HRN hrn(jcb);
hrn.run();
}
else if (k == 3) {
double slictTime;
cout <<"请输入第一级队列的时间片的大小:";
cin >> slictTime;
MFQ mfq(jcb, slictTime);
mfq.run();
}
else {
cout <<"输入数字有误,请重新输入"<< endl;
}
cout <<endl<<"请输入以下数字(1:时间片轮转调度算法;2:多级反馈队列调度算法;3:高响应比优先调度算法;0:退出)"<< endl;
};
return 0;
}。