编写并调试一个模拟的进程调度程序,以加深对进程的概念及进程调度算法的理解.
基本算法流程图:
处理机调度算法介绍:
1.短作业优先调度算法
优点:缩短作业的等待时间,提高系统的吞吐量。
缺点:对长作业不利。可能导致长作业长期不被调度而产生饥饿状态。完全未考虑作业的紧迫程度,因而不能保证紧迫性作业(进程)会被及时处理。
2.先来先服务
优点:比较有利于长作业,有利于CPU繁忙型作业,用于批处理系统,
缺点:而不利于短作业,不利于I/O繁忙型作业,不适于分时系统
3.高响应比优先算法:
优点:等待时间相同的作业,则要求服务的时间愈短,其优先权愈高,——对短作业有利
要求服务的时间相同的作业,则等待时间愈长,其优先权愈高,——是先来先服务
长作业,优先权随等待时间的增加而提高,其等待时间足够长时,其优先权便可升到很高, 从而也可获得处理机——对长作业有利,这种算法是一种折衷,既照顾了短作业,又考虑了作业到达的先后次序,又不会使长作业长期得不到服务。
缺点:要进行响应比计算,增加了系统开销
算法设计
每个进程采取结构体的形式进行存储。
对于三种优先级的算法设计,三个调度算法中所有进程都是以时间的转移而进行运行的。
先来先服务算法的优先级是以时间作为第一优先级进行排序,
短作业优先是以进程服务时间作为第一优先级,
高响应比是根据(等待时间+服务时间)/服务时间作为第一优先级。
#include<bits/stdc++.h>
using namespace std;
const int N = 1e5;
struct work{
int id;
int arriveTime;
int serviceTime;
int beginTime;
int waitTime;
int finishTime;
int runTime;
double weightrunTime;
double ratio;
bool operator < (const work &p)
{
return arriveTime < p.arriveTime;
}
}process[N];
int idx=0,n;
bool SJF(work a,work b) //短作业优先
{
if(a.serviceTime!=b.serviceTime) return a.serviceTime<b.serviceTime;
return a.id<b.id;
}
bool FCFS(work a,work b) //先来先服务
{
if(a.arriveTime!=b.arriveTime) return a.arriveTime<b.arriveTime;
return a.id<b.id;
}
bool HRRN(work a,work b)
{
if(a.ratio!=b.ratio) return a.ratio>b.ratio;
return a.id<b.id;
}
void hrrn() //高响应比
{
for(int i=idx;i<n;i++)
{
process[i].waitTime=process[idx-1].finishTime-process[i].arriveTime;
process[i].ratio=1.0*(process[i].waitTime+process[i].serviceTime)/process[i].serviceTime;
}
sort(process+idx,process+n,HRRN);
}
int main()
{
ifstream fin("C:\\Users\\13529\\Desktop\\processTestingData.txt"); //通过打开数据文件导入数据,无需手动输入
string item;
int cnt=0;
while(fin >> item)
{
if(cnt%3==0)
process[n].id=stoi(item);
if(cnt%3==1)
process[n].arriveTime=stoi(item);
if(cnt%3==2)
process[n].serviceTime=stoi(item);
cnt++;
if(cnt%3==0) n++;
}
sort(process,process+n);
cout<<"进程名 提交时间\t服务时间\t开始时间\t等待时间\t完成时间\t周转时间\t带权周转时间\n";
int i=0;
while(1)
{
// cout<<i<<endl;
if(idx>=n) break;
if(process[idx].arriveTime<=i)
{
process[idx].beginTime=i;
process[idx].waitTime=process[idx].beginTime-process[idx].arriveTime;
process[idx].finishTime=process[idx].beginTime+process[idx].serviceTime;
process[idx].runTime=process[idx].finishTime-process[idx].arriveTime;
process[idx].weightrunTime=1.0*process[idx].runTime/process[idx].serviceTime;
cout<<process[idx].id<<"\t"<<process[idx].arriveTime<<"\t\t"<<process[idx].serviceTime<<"\t\t"
<<process[idx].beginTime<<"\t\t"<<process[idx].waitTime<<"\t\t"<<process[idx].finishTime<<"\t\t"<<process[idx].runTime;
printf("\t\t%.2lf\n",process[idx].weightrunTime);
i+=process[idx].serviceTime;
idx++;
sort(process+idx,process+n,SJF); //如果要使用先来先服务,就用FCFS排序,短作业优先就用SJF,同时注释掉下一行代码
//hrrn(); //如果要使用高响应比,就把上一行的代码注释掉
}
else i++;
}
return 0;
}
测试数据:
通过打开桌面的processTestingData.txt文件处理数据
1 800 50
2 815 30
3 830 25
4 835 20
5 845 15
6 700 10
7 820 5
结果展示:
短作业优先:
先来先服务:
高响应比:
结果分析
经过对比发现高响应比的平均周转时间最短,即照顾了短进程又照顾了长进程,短作业优先中1号第二个进入队列,但是因为进程太大直到最后才执行产生了“饥饿”,先到先服务严格根据时间先后进行执行,导致平均周转时间最长。
真棒~~学习了~🎉🎉
可以的!!!
操作系统好评
起飞!!!