操作系统 进程调度实验 模拟 C++版

一、实验目的
编写并调试一个模拟的进程调度程序,以加深对进程的概念及进程调度算法的理解.

二、实验内容
调试运行“动态优先级”调度算法,给出运行结果。
采用“短进程优先”调度算法对五个进程进行调度。每个进程有一个进程控制块( PCB)表示。进程控制块可以包含如下信息:进程名、到达时间、需要运行时间、已用CPU时间、进程状态等等。
每个进程的状态可以是就绪 W(Wait)、运行R(Run)、或完成F(Finish)三种状态之一。 每进行一次调度程序都打印一次运行进程、就绪队列、以及各个进程的 PCB,以便进行检查。重复以上过程,直到所要进程都完成为止。
基本算法流程图:
pcb6.jpg

处理机调度算法介绍
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

结果展示
短作业优先:
sjf.jpg

先来先服务:
fcfs.jpg

高响应比:
hrrn.jpg

结果分析
经过对比发现高响应比的平均周转时间最短,即照顾了短进程又照顾了长进程,短作业优先中1号第二个进入队列,但是因为进程太大直到最后才执行产生了“饥饿”,先到先服务严格根据时间先后进行执行,导致平均周转时间最长。

猜你喜欢

转载自blog.csdn.net/Jay_fearless/article/details/112257056