时间片轮转算法的进程调度模拟程序
要求以文件的形式给出进程的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;
}
实现步骤
- 从文件中读取进程的相关信息,初始化pcb
- 初始化化就绪队列,用数据结构队列保存就绪的进程。
- 进行时间片轮转调度,过程都在程序里写的很清楚。