2021-04-30

作业调度

目的: 了解并掌握作业调度的功能,熟悉并掌握各种作业调度算法。
任务: 模拟实现先来先服务或者短作业优先调度算法。
实验内容
模拟实现FCFS和SJF调度。
设置作业体:作业名,作业的到达时间,服务时间,作业状态(W——等待,R——运行,F——完成),作业间的链接指针;
作业初始化:由用户输入作业名、服务时间、到达时间进行初始化,同时,初始化作业的状态为W。
显示函数:在作业调度前、调度中和调度后进行显示。
排序函数:对等待状态的作业按照调度算法排序(不同的调度算法排序方式不同),注意考虑到达时间。
调度函数:每次从等待队列队首调度已到达的适合的作业执行,状态变化。当服务结束时,状态变为F。
删除函数:撤销状态为F的作业。
实验要求:
①测试数据可以随即输入或从文件中读入;
②必须要考虑到作业的到达时间;
③最终能够计算每一个作业的周转时间、带权周转时间。

原理:
先来先服务(FCFS):
该算法既可以用于进程调度也可以用于作业调度,当作业调度使用该算法时,系统将按照作业到达的先后次序来进行调度,或者说她是优先考虑在系统中等待时间最长的作业,而不管该作业所需执行时间长短,从后备队列中选择几个最先进入该队列的作业,将它们调入内存,为他们分配资源和创建进程。然后把它们放入就绪队列。
短作业优先(非抢占式SJF):
以作业的长短来计算优先级,作业越短,其优先级越高。作业的长短是以作业所要求的的运行时间来衡量的。SJF算法可以用作进程调度和作业调度。在吧短作业优先调度算法用于作业调度时,它将从后备队列中选择若干估计运行时间最短的作业,优先将它们调入内存

代码:

#include <stdio.h>
#include <stdlib.h>
#define getpch(type) (type*)malloc(sizeof(type))

struct jcb { // 定义作业控制块JCB
	char name[10];
	char state; //作业状态,等待,运行,完成
	double super;  //优先级
	int atime;  //作业到达时间
	int ntime;  //作业需要的运行时间
	double Ttime;   //周转时间
	double Wtime;   //带权周转时间
	struct jcb* link;   //就绪队列链表
}*ready = NULL, *p;    //ready为就绪队列,p为正在运行的作业或新加的作业

typedef struct jcb JCB;

double finTime; //记录某作业完成时间
int nowtime = 0;
double totalTtime = 0, totalWtime = 0; //总周转时间,总带权周转时间
int length = 0; //总作业数
int cho;    //选择采用何种算法

void FCFS()  //建立先来先服务函数
{
	JCB *first, *second;
	int insert = 0;
	if ((ready == NULL) || ((p->atime) < (ready->atime))) //作业先来,插入队首
	{
		p->link = ready;
		ready = p;
	}
	else if (p->atime == ready->atime && p->ntime < ready->ntime)    //同时到达,设为短作业优先
	{
		p->link = ready;
		ready = p;
	}
	else // 作业比较到达时间,插入适当的位置中
	{
		first = ready;
		second = first->link;
		while (second != NULL)
		{
			if ((p->atime) < (second->atime)) //若插入作业比当前作业到达时间前
			{                               //插入到当前作业前面
				p->link = second;
				first->link = p;
				second = NULL;
				insert = 1;
			}
			else // 插入作业到达的时间最晚,则插入到队尾
			{
				first = first->link;
				second = second->link;
			}
		}
		if (insert == 0) first->link = p;
	}
}

void sort() //按照优先级对链表结点进行冒泡排序
{
	JCB *head;
	head = getpch(JCB);
	head->link = ready;
	JCB *q, *prep, *temp, *tail;
	tail = NULL;
	while (head->link != tail)
	{
		prep = head;
		q = head->link;
		while (q->link != tail)
		{
			if (q->super < q->link->super)
			{
				temp = q->link;
				prep->link = q->link;
				q->link = q->link->link;
				prep->link->link = q;
				q = temp;
			}
			//结点后移
			q = q->link;
			prep = prep->link;
		}
		tail = q;
	}
	ready = head->link;
	head->link = NULL;
	free(head);
}

void SJF() //建立优先级函数
{
	if (nowtime == 0)
		FCFS(); //还没有作业读入内存时,用先来先服务算法
	else
		sort(); //已经有作业读入内存后,按照优先级排序
}

void input() // 建立进程控制块函数
{
	int i, num;
	printf("\n 请输入需要添加的作业个数:");
	scanf("%d", &num);
	length += num;
	for (i = 0; i < num; i++)
	{
		//printf("\n 作业号No.%d:\n", i + 1);
		p = getpch(JCB);    //分配空间
		printf("\n 输入作业名:");
		scanf("%s", p->name);
		printf("\n请输入作业到达时间:");
		scanf("%d", &p->atime);
		printf("\n 输入作业需要的运行时间:");
		scanf("%d", &p->ntime);
		printf("\n");
		p->super = p->atime;
		p->state = 'w';
		p->link = NULL;
		if (cho == 1)
			FCFS(); // 调用先来先服务函数
		else
			SJF(); //调用短作业优先函数
	}
}

int space() //计算剩余作业数
{
	int len = 0;
	JCB* pr = ready;
	while (pr != NULL)
	{
		len++;
		pr = pr->link;
	}
	return(len);
}

void disp(JCB * pr) //建立进程显示函数,用于显示就绪进程
{
	if (cho == 1)
	{
		printf("\n作业名   到达时间   状态   需要的时间\n");
		printf(" %s", pr->name);
		printf("         %d", pr->atime);
		printf("         %c", pr->state);
		printf("        %d", pr->ntime);
		printf("\n");
	}
	else
	{
		printf("\n作业名   到达时间   状态   需要的时间   等待时间   优先级\n");
		printf(" %s", pr->name);
		printf("         %d", pr->atime);
		printf("         %c", pr->state);
		printf("        %d", pr->ntime);
		printf("           %d",pr->atime);
		printf("        %.2f", -pr->super);
		printf("\n");
	}
}

void destroy() //建立作业撤消函数(作业运行结束,撤消作业)
{
	printf("\n 作业 [%s] f.\n", p->name);
	free(p);
}

void running() // 运行内存中的作业
{
	finTime = nowtime; //完成时刻
	p->Ttime = finTime - p->atime; //周转时间
	p->Wtime = p->Ttime / p->ntime; //带权周转时间
	printf("\n作业名  提交时间  需要时间  完成时间  状态  周转时间  带权周转时间\n");
	printf("   %s       %d        %d        %.2f      %c     %.2f      %.2f\n", p->name, p->atime, p->ntime,
		finTime, p->state, p->Ttime, p->Wtime);

	totalTtime += p->Ttime;
	totalWtime += p->Wtime;
}

void check() // 建立作业查看函数
{
	JCB *pr;
	printf("\n **** 当前正在运行的作业是:%s", p->name); //显示当前运行的作业
	running();
	pr = ready;
	if (cho == 2)    //如果用短作业优先算法,
	{               //则有作业完成时要更新优先级且重新排序就绪队列
		while (pr != NULL)
		{
			if (nowtime < pr->atime)
			{
				
				pr = pr->link;
				continue;
			}
			else{
				pr->super=-pr->ntime;//点睛之笔,已经到达的按照运行时间分配优先权 
			}
			
			pr = pr->link;
		}
		SJF(); //重新排序
		pr = ready;
	}
	printf("\n ****当前就绪队列状态为:\n"); //显示就绪队列状态
	while (pr != NULL)
	{
		if (nowtime < pr->atime)
		{
			pr = pr->link;
			continue;
		}
		disp(pr);
		pr = pr->link;
	}
	destroy();
}

int main() //主函数
{
	int len;
	while (1)
	{
		printf("\t\t\t************************作业调度算法**************************\n\t\t\t" );
		printf("\t\t\t先来先服务算法:1\n\t\t\t    \t\t\t 短作业优先算法:2\n"); 
		printf("\t\t\t********************************************************\n\t\t\t");
		printf("\t\t\t请输入数字选择对应的调度算法: ");
		scanf("%d", &cho);
		printf("\n\t---------------------------------------------------------------\n");
		if (cho == 1 || cho == 2)
			break;
		else
		{
			printf("\t\t\t输入错误,请重新输入!\n\n");
			continue;
		}
	}
	input();
	len = space();
	finTime = ready->atime;
	while ((len != 0) && (ready != NULL))
	{
		getchar();
		p = ready;
		nowtime = p->ntime + finTime;
		printf("\n\n现在的时间是:%d \n", nowtime);
		ready = p->link;
		p->link = NULL;
		p->state = 'R';
		check();
	}
	if (cho == 1)
	{
		printf("\n 所以作业已经完成,先来先服务调度算法模拟结束\n\n");
	}
	else
	{
		printf("\n 所以作业已经完成,短作业优先调度算法模拟结束\n\n");
	}
	printf("本组作业的平均周转时间为:%.2f\n", totalTtime / length);
	printf("本组作业的平均带权周转时间为:%.2f\n", totalWtime / length);
	getchar();
	return 0;
}

输入及计算结果:
在这里插入图片描述

运行结果:
FCFS:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
SJF:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
开始做这个实验的时候,根本不知道从哪里下手,在网上找了很多代码都不太符合实验要求,其中有一篇基本符合要求却是先来先服务和高响应比实验代码,然后我就把高响应比改为了短作业的优先级,来实现短作业优先。原理就是没有到达的作业就依据到达时间来赋值优先级,已到达还没来得及运行的就依据运行时间赋值优先级。
我借鉴的博客在这里:先来先服务和高响应比

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值