时间片轮转算法实现

时间片轮转算法的进程调度模拟程序

要求以文件的形式给出进程的ID、到达时间和估计运行时间,设计一个模拟单处理机调度的时间片轮转算法,实现处理机的调度,在屏幕上打印每次调度的相关信息,包括:进程占用处理机序列,该进程执行的开始时间、进程运行结束时间、进程的周转时间和带权周转时间等。最后统计出平均周转时间和平均带权周转时间。

#include<stdio.h>
#include <stdlib.h>
#define N 50 //定义进程最大数 
#define T 1 //时间片 
struct PCB
{	int ci;	//进程被调度的次数 
	int ks;  //进程开始运行的时间 
	int pn;   //process name进程名字
	int at;   //arrival time到达时间
	int st;   //service time服务时间
	int ct;   //completion time完成时刻
	int sc;  //sign completion标志是否完成
	int st1;  //剩余服务时间  
}process[N];
 
 //定义队列节点 
typedef struct QNode{ 
	int data; 
	struct QNode *next; 
}QNode,*QueuePtr;
//定义队列
typedef struct{
	QueuePtr front; 
	QueuePtr rear;
}LinkQueue;
int InitQueue(LinkQueue &Q);        //初始化队列 
int DestroyQueue(LinkQueue &Q);//删除队列
int EnQueue(LinkQueue &Q,int e); //进入队列
int DeQueue(LinkQueue &Q,int e);//离开队列
bool QueueEmpty(LinkQueue &Q);//判读队列是否为空
int cun(LinkQueue &Q,int e);  //判断队列中是否存在此数 
 
int RR()
{
	LinkQueue Q;//创建队列
	int i,j,c;
	int n=0;//记录进程数 
	char fname[20];
	FILE *fp; 
	printf("注意:文件中应包含以下信息:\n");
	printf("进程ID    到达时间     估计运行时间  \n");
	printf("请输入进程流文件名:");
	scanf("%s",&fname);
	if((fp=fopen(fname,"r"))==NULL){
		printf("错误,文件打不开,请检查文件名");
		return 0;
	}else{
		while(1){
			
			if( feof(fp) ){ 
         		 break ;
     	 	}
     	 	//文件读取结束退出 process[0]不存储PCB,作为辅助 
			fscanf(fp,"%d %d %d ",&process[n+1].pn,&process[n+1].at,&process[n+1].st); 
			process[n+1].sc=0;
			process[n+1].ks=0;
			process[n+1].ci=0;
			process[n+1].st1=process[n+1].st;
			n++;
			//初始化,剩余服务时间等于服务时间 
		}
	}
	
	//按照各进程到达时间升序,对进程排序 
	for(i=1;i<=n;i++)
	for(j=i+1;j<=n;j++)  
	{
		if(process[j].at<process[i].at)
		{
			process[0]=process[j];
			process[j]=process[i];
			process[i]=process[0];	
		}
	}
//		for(i=1;i<=n;i++) printf("%d\n",process[i].pn);
	
	int time=process[1].at;      //当前时间的初值 
	printf("\n调度过程:\n");
	printf("\n第几次调度进程 运行的进程 开始运行时间 运行时间 剩余服务时间 结束时间\n");
	int z=1;   //记录第几次调度进程 
	InitQueue(Q);
	EnQueue(Q,1);
 	int yun=0; // 判断进程以那种方式开始 
 	//当队列不为空时 
 	while(QueueEmpty(Q)==false){
 		int i;
 		i=DeQueue(Q,i);
 		//出队 
 		if(process[i].st1<=T){
		 	process[i].ci++;
		 	//进程被调度次数+1 
		 	yun=2;
		 	time=time+process[i].st1;
		 	process[i].sc=1;
		 	int k;
		 	//如果有就绪进程就加入就绪队列 
		 	for(k=1;k<=n;k++){
		 		if(time>=process[k].at&&process[k].sc!=1&&cun(Q,k)==1){
		 			EnQueue(Q,k);
				}
			} 
		 	process[i].ct=time;
		 	printf("%8d%12d%15d%11d%11d%11d\n",z++,process[i].pn,time-process[i].st1,process[i].st1,0,time); 
		 	process[i].st1=0;
		 }else if(process[i].st1>T)//未完成的进程但其还需服务时间至少大于一个时间片 
		 	{
				int j,k; j=i;
		 		process[i].ci++;
		 		yun=1;
		 		time=time+T;
		 		//如果有就绪进程就加入就绪队列 
		 		for(k=1;k<=n;k++){
		 			if(time>=process[k].at&&j!=k&&process[k].sc!=1&&cun(Q,k)==1){
		 				EnQueue(Q,k);
					 }
				 }
				 //进程因为时间片用完转化为就绪队列 
				 EnQueue(Q,i);
				process[i].st1-=T;
				printf("%8d%12d%15d%11d%11d%11d\n",z++,process[i].pn,time-T,T,process[i].st1,time);
			} 
			//计算 进程开始运行时间 
			if (process[i].ci==1){
				if(yun==1){
					process[i].ks=time-T;
				}
				if(yun==2){
					process[i].ks=time-process[i].st1;	
				}
			}
	 }
 printf("\n调度的相关信息:\n");
 printf("\n进程ID 到达时间 服务时间 开始运行时间 结束时间  进程的周转时间  带权周转时间\n");
 	for(i=1;i<=n;i++){
		printf("%4d%8d%8d%10d%10d%14d            %.2f\n",process[i].pn,process[i].at,process[i].st,process[i].ks,process[i].ct,process[i].ct-process[i].at,(float)(process[i].ct-process[i].at)/process[i].st);
	} 
	float temp=0;
	printf("\n\n平均周转时间:");
	for(i=1;i<=n;i++){ 
		temp+=process[i].ct-process[i].at;
	} 
	temp=temp/n;
	printf("%f\n",temp);
	temp=0;
	printf("\n平均带权周转时间:");
	for(i=1;i<=n;i++){ 
		temp+=(float)(process[i].ct-process[i].at)/process[i].st;
	} 
	temp=temp/n;
	printf("%f",temp);

}
 
int main()
{
	printf("\n\n\t\t\t\t**********时间片轮转调度算法**********\n\n");
	RR();
	return 0;
}

//初始化队列 
int InitQueue(LinkQueue &Q){
	Q.front=Q.rear=(QueuePtr)malloc(sizeof(QNode));
	if(!Q.front)exit(-1);
	Q.front->next=NULL;
	return 1;
}
//进队 
int EnQueue(LinkQueue &Q,int e){
	QueuePtr p=(QueuePtr)malloc(sizeof(QNode));
	if(!p)
	exit(-1);
	p->data=e;
	p->next=NULL;
	Q.rear->next=p;
	Q.rear=p;
	return 1;
} 
//弹出最队尾元素 
int DeQueue(LinkQueue &Q,int e){
	QueuePtr p;
	if(Q.front==Q.rear)
	return 0;
	p=Q.front->next;
	e=p->data;
	Q.front->next=p->next;
	if(Q.rear==p)
	Q.rear=Q.front;
	free(p);
	return e;
}
//判断队列是否为空 
bool QueueEmpty(LinkQueue &Q){
	if(Q.front==Q.rear)
		return true;
	else
		return false;
}
//队列存在此数返回0,否则返回1 
int cun(LinkQueue &Q,int s){
	int a[100];
	int i;
	int sg=1;
	int n=0;
	while(QueueEmpty(Q)==false){
		int i;
 		i=DeQueue(Q,i);
 		a[n]=i;
 		n++;
	}
	for(i=0;i<n;i++){
		EnQueue(Q,a[i]);
	}
	for(i=0;i<n;i++){
		if(a[i] == s){
			sg=0;
		}
	}
	return sg;
}

实现步骤

  1. 从文件中读取进程的相关信息,初始化pcb
  2. 初始化化就绪队列,用数据结构队列保存就绪的进程。
  3. 进行时间片轮转调度,过程都在程序里写的很清楚。
  • 3
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值