操作系统原理与实验——实验二先来先服务调度算法

实验指南

运行环境:

Dev c++

算法思想

本实验是模拟进程调度中的先来先服务算法,每次CPU都是按照进入就绪队列的先后次序依次选中一个进程装入CPU运行,等结束时再选取下一个。

核心数据结果

struct Time {

    int hour, min;

};

struct node {

    int id;//编号你

    char name[20];//进程名

    Time arrive;//到达就绪队列时间

    int zx;//执行时间

    Time start;//开始时间

    Time finish;//完成时间

    int zz;//周转时间=完成时间-到达时间

    float zzxs;//带权周转系数=周转间/执行时间,下同

    struct node* next;

};

程序框架

//函数名:check,函数参数:Time x(当前进程的到达时间),Time y(待插入进程的到达时间)

bool check(Time x, Time y) {

    //函数功能:比较到达时间的早晚

}

struct Q{

    node *front, *end;

};

//函数名:init,函数参数:Q &x(含有就绪队列的队头和队尾节点地址)

void init(Q &x) {

     //函数功能:初始化,为之后操作做准备

}

//函数名:insert,函数参数:Q *x(指向含有就绪队列的队头和队尾节点的指针),node tmp()

void insert(Q *x, node tmp) {

    //函数功能:构建并按到达时间先后插入进程节点放入就绪队列中

}

//函数名:dele,函数参数:Q &x(含有就绪队列的队头和队尾节点地址)

void dele(Q &x) {

    //函数功能:初始化,为下一个进程序列做准备

}

//函数名:input,函数参数:Q &x(含有就绪队列的队头和队尾节点地址)

void input(Q &x) {

    //函数功能:输入节点信息,构建并按到达时间先后依次插入进程节点放入就绪队列中

 

}

//函数名:cal,函数参数:Time x(当前进程的开始时间), int y(当前进程的执行时间)

Time cal(Time x, int y) {

    //函数功能:计算当前进程的结束时间(开始时间+执行时间)

   

}

//函数名:deline,函数参数:Time x(上一进程的结束时间),Time y(当前进程的到达时间)

int deline(Time x, Time y) {

    //函数功能:计算进程的等待时间(即上一进程的结束时间与当前进程的到达时间的时间差)

   

}

//函数名:fcfs,函数参数:Q *x(指向含有就绪队列的队头和队尾节点的指针)

void fcfs(Q *x) {

    //函数功能:计算进程相关时间信息,分别确定开始时间,结束时间(开始时间+执行时间),周转时间(结束时间-到达时间),周转系数(周转时间/执行时间)

  

}

//函数名:output,函数参数:Q &x(含有就绪队列的队头和队尾节点的地址)

void output(Q &x) {

    //函数功能:按进程执行顺序分别输出每个进程全部结果信息和系统平均时间

}

int main() {

    Q x;

    while(1) {

       init(x);

       input(x);

       fcfs(&x);

       output(x);

       while(x.front != NULL) dele(x);

    }

    return 0;

}

测试用例:

14个进程:

100 p14 4:30 10
200 p13 3:20 10
400 p12 6:00 30
200 p11 7:10 40
5001 p1 19:40 20
5002 p4 10:10 10
5003 p5 10:05 30
5004 p2 9:55 15
5005 p3 9:45 25
5006 p6 11:40 20
5007 p8 12:10 10
5008 p9 13:05 30
5009 p10 19:55 15
5010 p7 7:15 15

5个进程:

5001 p1 9:40 20
5004 p4 10:10 10
5005 p5 10:05 30
5002 p2 9:55 15
5003 p3 9:45 25

10个进程:

5009 p9 19:40 20
5005 p5 10:10 10
5004 p4 10:05 30
5003 p3 9:55 15
5002 p2 9:45 25
5006 p6 11:40 20
5007 p7 12:10 10
5008 p8 13:05 30
5010 p10 19:55 15
5001 p1 7:15 15

关键代码

#include<stdio.h> 
#include<stdlib.h>
#include <malloc.h>
struct Time {
    int hour, min;
};
struct node {
    int id;//编号名 
    char name[20];//进程名
    Time arrive;//到达就绪队列时间
    int zx;//执行时间
    Time start;//开始时间
    Time finish;//完成时间
    int zz;//周转时间=完成时间-到达时间
    float zzxs;//带权周转系数=周转间/执行时间,下同
    struct node* next;
};
//函数名:check,函数参数:Time x(当前进程的到达时间),Time y(待插入进程的到达时间)
bool check(Time x, Time y) {
    //函数功能:比较到达时间的早晚
    if((y.hour>x.hour)||(y.hour==x.hour&&(y.min>x.min)))
    	return true;
	else
		return false;
    
}
struct Q{
    node *front, *end;
};void output(Q &x);
//函数名:init,函数参数:Q &x(含有就绪队列的队头和队尾节点地址)
void init(Q &x) {
     //函数功能:初始化,为之后操作做准备
	   x.front=NULL;
	   x.end=NULL;
}
//函数名:insert,函数参数:Q *x(指向含有就绪队列的队头和队尾节点的指针),node tmp()
void insert(Q *x, node tmp) {
    //函数功能:构建并按到达时间先后插入进程节点放入就绪队列中
    node*N=(node*)malloc(sizeof(node));
    node *p,*q;
    p=x->front;
    q=NULL;
    *N=tmp;
    N->next=NULL;
    if(p==NULL&&q==NULL)//没有结点 
    {
    	x->front=N;
    	x->end=N;
	}
	else//有结点 
	{
		while(p!=NULL)
		{
			if(p->next==NULL)
			{
				p->next=N;
				x->end=N;
				break;
			}
			p=p->next;
		} 
	}
	return ;
}
//函数名:dele,函数参数:Q &x(含有就绪队列的队头和队尾节点地址)
void dele(Q &x) {
    //函数功能:初始化,为下一个进程序列做准备
    node*p;
   	p=x.front;
   	x.front=x.front->next;
   	free(p);
}
//函数名:input,函数参数:Q &x(含有就绪队列的队头和队尾节点地址)
void input(Q &x) {
    //函数功能:输入节点信息,构建并按到达时间先后依次插入进程节点放入就绪队列中
    int flag; 
    printf("请输入操作(1:开始进度调度;0:结束进程):");
    scanf("%d",&flag);
    if(flag==0)
    {
    	printf("操作结束!");
    	exit(0);
	}
    else
    {
    	int n;
	    printf("请输入进程数量: ");
		scanf("%d",&n);
		printf("请输入进程的参数:\nid名 名字 到达时间 执行时间(分钟)\n");
	    while(n--)
	    {
	    	node *p=(node*)malloc(sizeof(node));
			scanf("%d %s %d:%d %d",&p->id,&p->name,&p->arrive.hour,&p->arrive.min,&p->zx);
			p->next=NULL;
			insert(&x,*p);
		}
	}
}
//函数名:cal,函数参数:Time x(当前进程的开始时间), int y(当前进程的执行时间)
Time cal(Time x, int y) {
    //函数功能:计算当前进程的结束时间(开始时间+执行时间)
    int m,h;
	m=(x.min+y)%60;
	h=x.hour+(x.min+y)/60;
	x.hour=h;
	x.min=m;
	return x;
}
//函数名:deline,函数参数:Time x(上一进程的结束时间),Time y(当前进程的到达时间)
int deline(Time x, Time y) {
    //函数功能:计算进程的等待时间(即上一进程的结束时间与当前进程的到达时间的时间差)
    int h;
    h=x.hour*60+x.min-y.hour*60-y.min;
	return h;
}
//函数名:fcfs,函数参数:Q *x(指向含有就绪队列的队头和队尾节点的指针)
void fcfs(Q *x) {
    //函数功能:计算进程相关时间信息,分别确定开始时间,结束时间(开始时间+执行时间),周转时间(结束时间-到达时间),周转系数(周转时间/执行时间)
   node*p,*q,*head=NULL,*pre;
   p=x->front;
   while(p!=NULL)
   {
   	node*N=(node*)malloc(sizeof(node));
   	*N=*p;
    N->next=NULL;
   	if(head==NULL)
   	{
   		head=N;
   		q=head;
	}
	else
	{
		pre=NULL;
		q=head;
		while(q!=NULL)
		{
		if(!check(head->arrive,N->arrive))
		{
			N->next=head;
			head=N;
			break;
		}
		else if(check(q->arrive,N->arrive)&&q->next==NULL)
		{
			q->next=N;
			x->end=N; 
			break;
		}
		else if(!check(q->arrive,N->arrive))
		{
			N->next=q;
			pre->next=N;
			break;
		}
		pre=q;
		q=q->next;
		}
	}
	p=p->next;
   }
   x->front=head;
   x->end=pre;   
   p=x->front;
   while(p!=NULL)
   {
   		if(p==x->front)
   		{
   			p->start.hour=p->arrive.hour;
   			p->start.min=p->arrive.min;
			p->finish=cal(p->start,p->zx);
			p->zz=p->zx; 
		}
		else
		{
			if((q->finish.hour>p->arrive.hour)||((q->finish.hour==p->arrive.hour)&&(q->finish.min>p->arrive.min)))
			{
				p->start.hour=q->finish.hour;
	   			p->start.min=q->finish.min;
				p->finish=cal(p->start,p->zx);
			}
			else
			{
				p->start.hour=p->arrive.hour;
	   			p->start.min=p->arrive.min;
				p->finish=cal(p->start,p->zx);
			}
			p->zz=deline(p->finish,p->arrive);
		}
		p->zzxs=p->zz*1.0/p->zx;
		q=p;
		p=p->next;
   }
}
//函数名:output,函数参数:Q &x(含有就绪队列的队头和队尾节点的地址)
void output(Q &x) {
    //函数功能:按进程执行顺序分别输出每个进程全部结果信息和系统平均时间
   int sum=0,count=0; 
   float sum1=0; 
   node*p;
   p=x.front;
   printf("模拟进程FCFS调度过程输出结果:\nid名    名字   到达时间   执行时间(分钟)   开始时间   完成时间  周转时间(分钟)  带权周转系数\n");
   while(p!=NULL)
   {
    	printf("%5d ",p->id);
    	printf("%5s ",p->name);
    	printf("%5d:%2d ",p->arrive.hour,p->arrive.min);
    	printf("%8d(分钟) ",p->zx);
    	printf("%14d:%2d ",p->start.hour,p->start.min);
    	printf("%7d:%2d ",p->finish.hour,p->finish.min);
    	printf("%7d ",p->zz);
    	printf("%20.2f\n",p->zzxs);
    	sum=sum+p->zz;
    	sum1=sum1+p->zzxs;
    	count++;
    	p=p->next;
   }
   printf("系统平均周转时间为:%.2f\n",sum*1.0/count);
   printf("系统平均带权周转系数为:%.2f\n",sum1/count);
}

int main() {
	Q x;
    while(1) {
    	init(x);//初始化 
    	input(x);//1函数功能:输入节点信息,构建并按到达时间先后依次插入进程节点放入就绪队列中
    	fcfs(&x);//2函数功能:计算进程相关时间信息,分别确定开始时间,结束时间(开始时间+执行时间),周转时间(结束时间-到达时间),周转系数(周转时间/执行时间)
    	output(x);//3函数功能:按进程执行顺序分别输出每个进程全部结果信息和系统平均时间
    	while(x.front != NULL) dele(x);
	}
    return 0;
}

运行结果

实验总结

①对*、&的运算还不是很理解,还得多加练习

②在创建单链表时,判断条件没有设计好,比如应该是p!=NULL,如果是p->next==NULL则最后一个结点的值没有比较

③在创建单链表时,对于插入操作中的遍历指针和前驱结点理解有误,导致单链表创建不出来(遍历指针用于遍历,前驱指针为了能插入结点做准备)

④没有理解指针与结点的区别,都分配了空间,造成空间的浪费

⑤在传入node tmp的参数时,如果没有重新分配空间,并对其赋值的话,链表也无法创建

⑥对链表的创建,刚开始输入结点值后并没有输出信息,因为结点的指针没有加以判断,导致链表无法创建。

  • 21
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值