操作系统实验(三)——安师大

实验3 进程调度

一、实验目的

多道程序系统中,当就绪进程数大于处理机数时,须按照某种策略决定哪些进程优先占用处理机。本实验模拟实现进程调度算法,以加深对进程概念和调度算法的理解。

二、实验要求

(1)问题描述

编程实现多级反馈队列调度算法,并给出各个进程的完成时间、周转时间、带权周转时间、以及平均带权周转时间。

(2)基本要求

  • 至少能实现三级反馈队列(即至少包括三个就绪队列,分别为队列1、队列2、队列3);
  • 需考虑进程被阻塞的情况,以及调度过程中有新进程到到达的情况;
  • 要求展现出调度的过程。

三、设计

(1) 多级反馈队列调度算法的基本思想:

设置多个就绪队列,并为各个队列赋予不同的优先级。

第一个队列的优先级最高,第二个队列次之,其余各队列的优先级逐个降低;在优先级愈高的队列中,为每个进程所规定的执行时间片愈小。

当一个新进程进入内存后,先将它放入第一队列末尾,按FCFS等待调度。

当轮到它执行时,如能在该时间片内完成,便可准备撤离;

如在一个时间片结束时尚未完成,调度程序便将其降入第二队列末尾,再同样地按FCFS原则等待调度执行;

如在第二队列中运行一个时间片后仍未完成,再依次将它放入第三队列,如此下去,当一个长作业(进程)从第一队列依次降到第n队列后,在第n队列中便采取按RR方式运行。

(2)主要功能模块

  • 进程初始化;
  • 显示初始化后进程的基本信息;
  • 多级反馈队列调度(包括当前进程被阻塞、检查是否有高优先级的进程);
    1. 若当前进程没被阻塞,且剩余的服务时间不为0,则当前进程进入下一级队列的队尾(需进行特殊情况的检查:若当前进程已在最后一个队列中,则进入原队列的队尾)。
    2. 若当前进程被阻塞,要将该进程放入相应的阻塞队列,并且要记录下被阻塞时所处的队列编号,以便于唤醒时回到原队列中;
    3. 每运行一个时间单位,需判断是否有高优先级进程进入系统或被唤醒,若有,则调度该优先级高的进程(即高优先级队列中的进程),否则,仍调度当前队列中的进程;
    4. 若当前队列为空,则调度下一级队列中的进程。
  • 显示调度的过程以及各进程的完成时间、周转时间、带权周转时间,以及平均带权周转时间。

(3)输入

进程数、进程标识、进程的到达时间、服务时间、优先级、对应的时间片大小等。由于新创建的进程先进入队列1中,因此,此处优先级就是队列1(即最高优先级队列)的优先级,时间片大小就是队列1的时间片大小,而其余各队列的时间片以该时间片为基础计算而得,例如:若初始化的时间片q1=1,则另外两个队列的时间片可分别为是q2=q1*2、q3=q2*2;对于优先级也可用类似方法进行处理,如p1=10,p2=p1-2,p3=p2-2。注意初始化进程时,各进程所对应的时间片大小以及优先级都是一样的,都是队列1对应的优先级以及时间片大小。

如:

进程数:2

进程的初始化:

1,0,3,10,1

2,2,2,10,1

由上述初始化信息,可知队列1的优先级为10,时间片大小为1

(4)输出

显示调度的过程(如哪个时刻调度队列X中的进程Y,运行多长时间,还需服务时间等),以及各个进程名、对应的完成时间、周转时间和带权周转时间和整体的平均带权周转时间。

四、实验代码

1.PCB设计-多级反馈.h

#include <stdio.h>
#include <malloc.h>
#include <queue> //
using namespace std;//调用命名空间std内定义的所有标识符 

typedef struct PCB{//PCB数据结构的设计 
	int id;//进程标识符 
	int arrivetime; //到达时间 
	int servetime;//服务时间 
	int finishtime;//完成时间 
	int priority;//优先级 
	int timep;//时间片大小 
	struct PCB *next;//设置PCB为链接方式 
}PCB;

 2.进程初始化

#include "多级反馈.h"

int time=0;
float sum=0;
//进程初始化 
void InitPCB(PCB &work, int id, int arrivetime, int servetime, int priority, int timep){
	work.id=id;
	work.arrivetime=arrivetime;
	work.servetime=servetime;
	work.priority=priority;
	work.timep=timep;
}

3.队列一和队列二执行FCFS算法

//队列1和队列2执行fcfs算法 
void fcfs(queue<PCB> &q1, queue<PCB> &q2,int id){
	
	printf("\n第%d级(fcfs)\n",id); 
	
	//当一个新进程进入内存后,先将它放入第一队列末尾,按FCFS等待调度。 
	while(!q1.empty()){ 
		PCB s=q1.front();
		printf("时间:%d ",time);
		if(time>=s.arrivetime){
			printf("进程%d 运行时间%d ",s.id,s.timep);
			//运行一个时间片 
			for(int i=0;i<s.timep;i++){
				time++;
				s.servetime--;
			}
			s.timep=s.timep*2;
			s.priority-=2;
			//若运行完成 
			if(s.servetime<=0){ 
				s.finishtime=time;         //结束时间 
				int zhouzhuan=s.finishtime-s.arrivetime;        //周转时间 
				float daiquan=((float)zhouzhuan)/(s.servetime+timeloss(id));//带权周转时间 
				printf("运行完成 ");
				printf("完成时间%d 周转时间%d 带权周转时间%.1f\n",s.finishtime,zhouzhuan,daiquan);
				sum+=daiquan;
				q1.pop();//已完成的进程离开系统
				continue; 
			}else{//若运行未完成 
				q1.pop(); //已执行一次的进程离开队列 1
				q2.push(s);//转入队列2 
				printf("还需服务时间%d\n",s.servetime);
			}
		}else{//等待进程到达 
			time++;
			printf("\n");
		}
	}
	//循环结束,q1为空,展示q2
	printf("第%d级执行完成,下级进程:\n",id);
	dispQueue(q2); 
}

4.队列三执行时间片轮转算法 

//队列3执行时间片轮转算法 
float rr(queue<PCB> &q3){
	printf("\n第3级(rr)\n"); 
	while(!q3.empty()){
		PCB s=q3.front();
		printf("时间:%d ",time);
		if(time>=s.arrivetime){
			printf("进程%d 运行时间%d ",s.id,s.timep);
			//运行一个时间片 
			for(int i=0;i<s.timep;i++){
				time++;
				s.servetime--;
			}
			
			//若运行完成 
			if(s.servetime<=0){ 
				s.finishtime=time;                         //结束时间 
				int zhouzhuan=s.finishtime-s.arrivetime;        //周转时间 
				float daiquan=(zhouzhuan*1.0)/(s.servetime+timeloss(3));//带权周转时间 
				printf("运行完成 ");
				printf("完成时间%d 周转时间%d 带权周转时间%.1f\n",s.finishtime,zhouzhuan,daiquan);
				sum+=daiquan;
				q3.pop();//已完成的进程离开系统
				continue; 
			}else{//若运行未完成 
				q3.pop(); //先出队列3 
				q3.push(s);//再入队列3 
				printf("还需服务时间%d\n",s.servetime);
			}
		}else{
			time++;
		}
	}
	//循环结束
	printf("所有进程执行完成\n");
	return sum; //返回带权周转时间的和 
}

各级执行过的时间片数量

//计算进程在各级执行过的时间片数量 
int timeloss(int n){
	int i,j,time=0;
	for(i=0,j=1;i<n;i++,j*=2){
		time+=j;
	}
	return time;
}

5.多级反馈主函数

#include "多级反馈.cpp"

int main (){
	PCB work;
	queue<PCB> q1,q2,q3;//队列1,2,3 
	float avg,sum;
	int n;//进程数 
	int id,arrivetime,servetime,priority,timep;
	
	//初始化进程 
	printf("请输入进程数:");
	scanf("%d",&n);
	printf("请输入进程标识,到达时间,服务时间,优先级,对应的时间片大小:\n");
	for(int i=0;i<n;i++){
		scanf("%d%d%d%d%d",&id,&arrivetime,&servetime,&priority,&timep);
		InitPCB(work,id,arrivetime,servetime,priority,timep);
		q1.push(work);//进程入队列1执行 
	}
	printf("初始化完成,队列1信息:\n");
	dispQueue(q1);
	
	//多级反馈队列调度算法 
	fcfs(q1,q2,1); //第一级 
	fcfs(q2,q3,2); //第二级 
	sum=rr(q3);    //第三级 
	
	avg=sum/n;
	printf("平均带权周转时间为%.2f\n",avg);
	return 0;
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

京海第一深情xin

你的鼓励将是我创作最大的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值