我的大学之操作系统(三)

实验三

【实验题目】:高响应比优先调度和时间片轮转RR进程调度算法

【实验目的】
通过这次实验,加深对进程调度概念的理解,进一步掌握比FCFS和SJF更为复杂的进程调度算法的实现方法。

【实验内容及要求】
算法思路:
时间片轮转RR进程调度算法:用于分时系统中的进程调度。每次调度时,总是选择就绪队列的队首进程,让其在CPU上运行一个系统预先设置好的时间片。一个时间片内没有完成运行的进程,返回到绪队列末尾重新排队,等待下一次调度。
给每个进程固定的执行时间,根据进程到达的先后顺序让进程在单位时间片内执行,执行完成后便调度下一个进程执行,时间片轮转调度不考虑进程等待时间和执行时间,属于抢占式调度。优点是兼顾长短作业;缺点是平均等待时间较长,上下文切换较费时。适用于分时系统。
高响应比优先算法:①当等待时间相同时,短进程的优先权高;②当需要运行时间相同时,作业的优先权又取决于等待时间,相当于先到先服务;③长作业的优先级可以随着等待时间的增加而提高,因此长作业等待一段时间后仍能得到调度。
使用的公式:
完成时间 = 开始时间 + 需要运行时间
周转时间 = 完成时间 - 到达时间
带权周转时间 = 周转时间 / 需要运行时间
等待时间 = 当前时间 - 到达时间
优先权 = (等待时间 + 需要运行时间) / 需要运行时间
问题描述:
设计程序模拟进程的高响应比优先调度和时间片轮转RR调度过程。假设有n个进程分别在T1, … ,Tn时刻到达系统,它们需要的服务时间分别为S1, … ,Sn。如果选择RR算法,则需要指定时间片大小q,采用时间片轮转RR进程调度算法进行调度,如果选择高响应比优先调度算法,则可以直接调度,计算每个进程的完成时间,周转时间和带权周转时间,并且统计n个进程的平均周转时间和平均带权周转时间。
程序要求如下:
1)进程个数n;每个进程的到达时间T1, … ,Tn和服务时间S1, … ,Sn;如果选择时间片轮转法,则要输入时间片大小q。
2)要求高响应比优先和时间片轮转法RR调度进程运行,计算每个进程的周转时间,带权周转时间,并且计算所有进程的平均周转时间,带权平均周转时间;
3)输出:要求模拟整个调度过程,输出每个时刻的进程运行状态,如“时刻3:进程B开始运行”等等;
4)输出:要求输出计算出来的每个进程的周转时间,带权周转时间,所有进程的平均周转时间,带权平均周转时间。
【流程图】
在这里插入图片描述

【实验结果】
核心代码:
时间片轮转RR进程调度:

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

高响应比优先调度:
在这里插入图片描述

可读文本文件:

在这里插入图片描述

实验结果截图:
时间片轮转RR进程调度:
在这里插入图片描述

高响应比优先调度:

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

【源代码】

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <iostream>
#include <queue>
#include <iomanip>
#include <fstream>
using namespace std;
#define WAIT "Wait"//就绪状态 
#define RUN "Run"//运行状态 
#define FINISH "Finish"//完成状态 
#define JOBNUMBER 5 //设置进程测试数为5  

//存放每个进程信息的结构体
typedef struct{
    char name;//进程名字
    int ArrivalTime;//到达时间
    int ServiceTime;//服务时间
    int FinishedTime;//完成时间
    int WholeTime;//周转时间
    double WeightWholeTime;//带权周转时间
}RR;
 
static queue<RR>RRqueue;  //用来模拟进程执行RR调度算法的队列
static double SumWT=0,SumWWT=0,AverageWT =0,AverageWWT=0;//平均周转时间、平均带权周转时间
static int q;  //时间片数
static int n;  //进程个数
static RR RRarray[100];  //进程结构体
static RR temp;  //进程结构
 
void Enter();//输入时间片、到达时间、服务时间等
void RRfunction();//执行RR调度算法
void display();//显示各时间执行情况,以及各个时间值
 
//输入时间片、到达时间、服务时间等
void Enter(){
    int i,j;
    cout<<"Enter n: ";
    cin>>n;
    cout<<"Enter TimeSlice q: ";
    cin>>q;
 
    for (i=0;i<n;i++){
      RRarray[i].name=i+65;//自动将进程名字顺序编号为A、B、C、D、E等
    }
 
    cout<<"Enter ArrivalTime: ";
    for (i=0;i<n;i++){
      cin>>RRarray[i].ArrivalTime;
    }
 
    cout<<"Enter ServiceTime: ";
    for (i=0;i<n;i++){
      cin>>RRarray[i].ServiceTime;
    }
 
    //根据达时间排序
    for(i=0;i<n;i++) {
        for(j=i+1;j<n;j++) {
            if(RRarray[i].ArrivalTime > RRarray[j].ArrivalTime) {
                temp = RRarray[i];
                RRarray[i] = RRarray[j];
                RRarray[j] = temp;
            }
        }
    }
}
 
//执行RR调度算法
void RRfunction(){
    char Moment[100];   //存储每个时间片p对应的进程名称
    RRqueue.push(RRarray[0]);   //第一个进程进队列
 
    int MomentPoint = 0;
    int CurrentTime=0;
    int tempTime;   //控制CurrentTime的累加时间,当前进程的服务时间小于时间片q的时候,起到重要作用
    int i=1,j;  //指向还未处理的进程的下标
    int finalNumber = 0;   //执行RR算法后,进程的个数
    int Time[50];
    bool canAdd=false;//用于解决CurrentTime在第一个进程完成计算时多加了一次服务时间的问题
 
    //判断第一个进程的服务时间是否大于时间片,如果大于CurrentTime=q,如果小于CurrentTime=服务时间
    if (RRarray[0].ServiceTime>=q)
        CurrentTime = q;
    else
        CurrentTime = RRarray[0].ServiceTime;
 
    while(!RRqueue.empty()){
 
        for (j=i;j<n;j++){   //使得满足进程的到达时间小于当前时间的进程都进入队列
            if (RRarray[j].name!=NULL && CurrentTime >= RRarray[j].ArrivalTime){
                RRqueue.push(RRarray[j]);
                i++;
            }
        }
        if (RRqueue.front().ServiceTime<q)
            tempTime = RRqueue.front().ServiceTime;
        else
            tempTime = q;
 
 
        RRqueue.front().ServiceTime -= q;   //进程每执行一次,就将其服务时间 -q
 
        //将队首进程的名称放入数组中
        Moment[MomentPoint] = RRqueue.front().name;
        MomentPoint++;
        Time[finalNumber] = tempTime;
        finalNumber++;
 
 
        if (RRqueue.front().ServiceTime <= 0)  //把执行完的进程退出队列
            RRqueue.pop();   //如果进程的服务时间小于等于,即该进程已经服务完了,将其退栈
        else{
            //将队首移到队尾
            RRqueue.push(RRqueue.front());
            RRqueue.pop();
        }
       if(canAdd){
         CurrentTime += tempTime;
 
       }
       canAdd=true;
 
 
    }
 
 
   //进程输出处理   每个时间段对应的执行的进程
 
	cout<<"各进程的执行时刻信息:"<<endl;
 
	Time[finalNumber]=0;
	int time = Time[0];
 
	int count = 0;
	int countTime=0;
 
	for (i=0;i<finalNumber;i++)//计算完成时间
	{
 
		count = 0;
 
 
		while(RRarray[count].name!=Moment[i] && count<n)
		{
 
			count++;
		}
		RRarray[count].FinishedTime = time;
 
		if (i<finalNumber - 1)
		{
 
			time += Time[i+1];
		}
 
 
	}
 
	for(i=0;i<finalNumber;i++){//输出
            	 for(int j=0;j<Time[i];j++){
            cout<<setw(3)<<countTime<<" --"<<setw(3)<<countTime+1<<setw(6)<<"时刻     "<<"进程"<<Moment[i]<<"执行";
           for(int k=0;k<n;k++){
            if(RRarray[k].ArrivalTime==countTime){
                cout<<"   进程"<<RRarray[k].name<<"到达";
            }
            else if(RRarray[k].FinishedTime==countTime+1&&countTime!=0){
                cout<<"   进程"<<RRarray[k].name<<"完成";
            }
           }
            countTime+=1;
           cout<<endl;
 
 
	    }
 
	}
	cout<<endl;
 
 
 
 
 
    //周转时间、带权周转时间、平均周转时间、带权平均周转时间的计算
    for (i=0;i<n;i++){
        RRarray[i].WholeTime = RRarray[i].FinishedTime - RRarray[i].ArrivalTime;
        RRarray[i].WeightWholeTime = (double)RRarray[i].WholeTime/RRarray[i].ServiceTime;
    }
 
    for (i=0;i<n;i++){
        SumWT += RRarray[i].WholeTime;
        SumWWT += RRarray[i].WeightWholeTime;
    }
    AverageWT = SumWT/n;
    AverageWWT = SumWWT/n;
 
}
 
//显示各时间执行情况,以及各个时间值
void display(){
    int i;
    //输出各个时间
    cout<<"ID"<<"\t";
    cout<<"ArrivalTime"<<"\t";
    cout<<"ServiceTime"<<"\t";
    cout<<"FinishTime"<<"\t";
    cout<<"WholeTime"<<"\t";
    cout<<"WeightWholeTime"<<endl;
    for (i=0;i<n;i++){
        cout<<RRarray[i].name<<"\t\t";
        cout<<RRarray[i].ArrivalTime<<"\t\t";
        cout<<RRarray[i].ServiceTime<<"\t\t";
        cout<<RRarray[i].FinishedTime<<"\t\t";
        cout<<RRarray[i].WholeTime<<"\t\t";
        cout<<setprecision(3)<<RRarray[i].WeightWholeTime<<"\t\t"<<endl;;
    }
    cout<<"SumWT = "<<setprecision(3)<<SumWT<<endl;
    cout<<"SumWWT = "<<setprecision(3)<<SumWWT<<endl;
    cout<<"AverageWT = "<<setprecision(3)<<AverageWT<<endl;
    cout<<"AverageWWT = "<<setprecision(3)<<AverageWWT<<endl;
}

 
typedef struct JCB{	
	char jobName[10];//作业名 
	int arriveTime;//到达时间 
	int runTime;//需要运行时间 
	int startTime;//开始时间 
	int endTime;//完成时间 
	int turnoverTime;//周转时间 
	float useWeightTurnoverTime;//带权周转时间
	char processStatus[10];//进程状态 	
};
static int currentTime = 0;//当前时间 
static int finishNumber = 0;//进程完成数量 
char JobArray[JOBNUMBER][10];//存放数组名信息的二元数组 
float priority[JOBNUMBER];//存放进程优先级的一元数组 
 
//创建JCB
void createJCB(struct JCB* jcb){
 	freopen("input.txt","r",stdin);
 	printf("从文件中读入三个参数的数据:\n");
 	printf("作业号 到达时间 需要运行时间\n"); 
 	for(int i = 0; i < 5; i++){
	 	scanf("%s", &jcb[i].jobName);//作业号 
	 	scanf("%d", &jcb[i].arriveTime);//到达时间 
	 	scanf("%d", &jcb[i].runTime);//需要运行时间 
	 	jcb[i].startTime = 0;
	 	jcb[i].endTime = 0;
	 	jcb[i].turnoverTime = 0;
	 	jcb[i].useWeightTurnoverTime = 0.0;
	 	strcpy(jcb[i].processStatus, WAIT);
	 	printf("%s\t%d\t%d\n",jcb[i].jobName, jcb[i].arriveTime,jcb[i].runTime);
	}
	printf("---------------------------------------------\n");
	freopen("CON", "r", stdin);
 }
 
//打印用途
void printJob(struct JCB* jcb){
	printf("当前时间为%d\n", currentTime);
	printf("作业号 到达时间 需要运行时间 开始时间 完成时间 周转时间 带权周转时间 进程状态\n");
	for(int i = 0; i < JOBNUMBER; i++){	
		if(strcmp(jcb[i].processStatus, FINISH) == 0)//如果进程为finish状态,这样输出 
			printf("%s\t%d\t%4d\t\t%d\t%d\t  %d\t  %.2f\t  %s\n", jcb[i].jobName, jcb[i].arriveTime, jcb[i].runTime, jcb[i].startTime, jcb[i].endTime, jcb[i].turnoverTime, jcb[i].useWeightTurnoverTime, jcb[i].processStatus);	
		else if(strcmp(jcb[i].processStatus, RUN) == 0)//如果进程为run状态,这样输出 
			printf("%s\t%d\t%4d\t\t%d\t运行中\t  none\t  none    %s\n", jcb[i].jobName, jcb[i].arriveTime, jcb[i].runTime, jcb[i].startTime, jcb[i].processStatus);	
		else //如果进程为wait状态,这样输出
			printf("%s\t%d\t%4d\t\t未运行\tnone\t  none\t  none    %s\n", jcb[i].jobName, jcb[i].arriveTime, jcb[i].runTime, jcb[i].processStatus);
	}
	printf("---------------------------------------------\n");
}
 
//计算平均带权周转时间 
float weightTurnoverTimeCount(struct JCB* jcb){
	float sum = 0.0;
	for(int i = 0; i < JOBNUMBER; i++)
		sum += jcb[i].useWeightTurnoverTime;
	return sum / JOBNUMBER;
}
 
//计算平均周转时间 
float turnOverTimeCount(struct JCB* jcb){
	float sum = 0.0;
	for(int i = 0; i < JOBNUMBER; i++)
		sum += jcb[i].turnoverTime;
	return sum / JOBNUMBER;
}
 
//比较各个进程之间的到达时间,按升序排列 
void compare(struct JCB* jcb){
	for(int i = 0; i < JOBNUMBER; i++){
		int min = jcb[i].arriveTime, minIndex = i;
		for(int j = i + 1; j < JOBNUMBER; j++){
			if(jcb[j].arriveTime < min){
				min = jcb[j].arriveTime;
				minIndex = j;		
			}	
		}
		struct JCB temp = jcb[i];
		jcb[i] = jcb[minIndex];
		jcb[minIndex] = temp;
	}	
}
 
//打印进程调度顺序,平均周转时间及平均带权周转时间 
void printInfo(struct JCB* jcb){
	printf("1、进程调度顺序为:%s -> %s -> %s -> %s -> %s\n", JobArray[0], JobArray[1], JobArray[2], JobArray[3], JobArray[4]);
	printf("2、平均周转时间为:%.2f\n",turnOverTimeCount(jcb));
	printf("3、平均带权周转时间为:%.2f\n", weightTurnoverTimeCount(jcb));
	printf("----------------------------------------------\n");
}
 
//两算法共同循环遍历部分 
void loop(struct JCB* jcb, int i){
	jcb[i].startTime = currentTime;
	jcb[i].endTime = jcb[i].startTime + jcb[i].runTime;
	jcb[i].turnoverTime = jcb[i].endTime - jcb[i].arriveTime;
	jcb[i].useWeightTurnoverTime = jcb[i].turnoverTime * 1.0 / jcb[i].runTime;
	strcpy(jcb[i].processStatus, RUN);
	while(true){
		if(currentTime == jcb[i].endTime){	
			strcpy(jcb[i].processStatus, FINISH);
			finishNumber++;
			if(finishNumber == JOBNUMBER)
				printJob(jcb);
			currentTime--;
			break;
		}
		else{
			printJob(jcb);
			currentTime++;	
		}	
	}
} 
 

//高响应比优先调度算法 
void highestResponseRatioNext(struct JCB* jcb){
	createJCB(jcb);
	compare(jcb);
	int i = 0, j = 0; 
	for(; finishNumber != JOBNUMBER; currentTime++){
		float maxPriority = 0.0;
		int indexPriority = 0;
		if(currentTime < jcb[0].arriveTime)//当前时间小于第一个节点到来时间时,直接打印 
			printJob(jcb);
		else{
			for(int i = 0; i < JOBNUMBER; i++){
				if(strcmp(jcb[i].processStatus, FINISH) != 0){
					int waitTime = currentTime - jcb[i].arriveTime;
				 	priority[i] = (waitTime + jcb[i].runTime) * 1.0 / jcb[i].runTime;
				 	if(priority[i] > maxPriority){
			 			maxPriority = priority[i];
			 			indexPriority = i;
			 		}
				}			 	
			}
			strcpy(JobArray[j++], jcb[indexPriority].jobName);
			loop(jcb, indexPriority);
		}
	}
	printInfo(jcb);//打印进程调度顺序,平均周转时间及平均带权周转时间 
	currentTime = 0;//当前时间置位
	finishNumber = 0;//完成进程数量置位 
}
 
//菜单函数
void menu(struct JCB* jcb){
	int input; 
	while(true){
		printf("----------------------------------------------\n");
		printf("|        1、时间片轮转RR进程调度算法         |\n");
		printf("|        2、响应比高者优先调度算法           |\n");
		printf("|        3、退出                             |\n");
		printf("----------------------------------------------\n");
		printf("请输入序号以继续程序:");
		scanf("%d", &input);
		switch(input){
			case 1: Enter();
					RRfunction();
					display();
				break;
			case 2:highestResponseRatioNext(jcb);
				break;
			case 3:
				exit(0);
			default:printf("输入有误,请重新输入!!!\n");
				break; 
		}	
	}
} 
 
//主函数 
int main(){
	struct JCB jcb[JOBNUMBER];
	menu(jcb);
    system("pause");
	return 0;

}

参考网址:https://blog.csdn.net/qq_40695551/article/details/84932694
https://blog.csdn.net/remoa_dengqinyi/article/details/52961771

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值