计算机操作系统实验二、作业调度

一、 实验目的:

     ~~~~      用高级语言编写和调试一个或多个作业调度的模拟程序,以加深对作业调度算法的理解。

二、 实验内容:

  1. 写并调试一个单道处理系统的作业等待模拟程序。
  2. 作业等待算法:分别采用先来先服务(FCFS)、响应比高者优先(HRN)的调度算法。
  3. 由于在单道批处理系统中,作业一投入运行,它就占有计算机的一切资源直到作业完成为止,因此调度作业时不必考虑它所需要的资源是否得到满足,它所占用的 CPU时限等因素。
  4. 每个作业由一个作业控制块JCB表示,JCB可以包含如下信息:作业名、提交时间、所需的运行时间、所需的资源、作业状态、链指针等等。作业的状态可以是等待W(Wait)、运行R(Run)和完成F(Finish)三种状态之一。每个作业的最初状态总是等待W。
  5. 对每种调度算法都要求打印每个作业开始运行时刻、完成时刻、周转时间、带权周转时间,以及这组作业的平均周转时间及带权平均周转时间。

三、 思考:比较各种算法的优缺点。

     ~~~~      先来先服务调度算法(FCFS):根据进程到达的先后顺序执行进程,不考虑等待时间和执行时间,会产生饥饿现象。属于非抢占式调度,优点是公平,实现简单;缺点是不利于短作业。
     ~~~~      高响应比优先调度算法:根据“响应比=(进程执行时间+进程等待时间)/ 进程执行时间”这个公式得到的响应比来进行调度。高响应比优先算法在等待时间相同的情况下,作业执行的时间越短,响应比越高,满足段任务优先,同时响应比会随着等待时间增加而变大,优先级会提高,能够避免饥饿现象。优点是兼顾长短作业,类似于SJF算法,有利于短作业,缺点是计算响应比开销大,适用于批处理系统

四、主要的数据结构

  1. 先来先服务(FCFS):
    包含作业名、到达时间、所需的运行时间、开始时间、完成时间、周转时间,带权周转时间及进程状态的结构体 JCB ,链表及队列
  2. 响应比高者优先(HRN): 包含作业名、到达时间、所需的运行时间、开始时间、完成时间、周转时间,带权周转时间及进程状态的结构体 JCB ,链表及队列

五、算法流程图

先来先服务(FCFS):
计算机操作系统实验二、作业调度_第1张图片
最高比响应优先(HRN):
计算机操作系统实验二、作业调度_第2张图片

六、运行与测试

先来先服务算法:
计算机操作系统实验二、作业调度_第3张图片计算机操作系统实验二、作业调度_第4张图片计算机操作系统实验二、作业调度_第5张图片
计算机操作系统实验二、作业调度_第6张图片
高响应比优先算法:
计算机操作系统实验二、作业调度_第7张图片计算机操作系统实验二、作业调度_第8张图片计算机操作系统实验二、作业调度_第9张图片
计算机操作系统实验二、作业调度_第10张图片

七、总结

     ~~~~      通过这次的实验,我深入理解作业的调度算法响应比高者优先算法、先来先服务算法的调度过程,通过对两种算法的运行效率分析,掌握到进程调度算法的实际应用需求,加深了我对进程调度的理解。

八、代码附录

#include 
#include 
#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 HRRN() //建立响应比高者优先函数
{
	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 = (nowtime - p->atime) / p->ntime + 1;
		p->state = 'w';
		p->link = NULL;
		if (cho == 1)
			FCFS(); // 调用先来先服务函数
		else
			HRRN(); //调用高响应比优先函数
	}
}

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

void disp(JCB * pr) //建立进程显示函数,用于显示就绪进程
{
	if (cho == 0)
	{
		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", nowtime - pr->atime);
		printf("        %.2f", pr->super);
		printf("\n");
	}
}

void destroy() //建立作业撤消函数(作业运行结束,撤消作业)
{
	printf("\n 作业 [%s] 已完成.\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 == 1)    //如果用高响应比优先算法,
	{               //则有作业完成时要更新响应比且重新排序就绪队列
		while (pr != NULL)
		{
			if (nowtime < pr->atime)
			{
				pr = pr->link;
				continue;
			}
			pr->super = ((nowtime - pr->atime) * 1.0) / pr->ntime + 1; //更新响应比
			pr = pr->link;
		}
		HRRN(); //重新排序
		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先来先服务算法:0\n\t\t\t    \t\t\t 高响应比优先算法:1\n"); 
		printf("\t\t\t********************************************************\n\t\t\t");
		printf("\t\t\t请输入数字选择对应的调度算法: ");
		scanf("%d", &cho);
		printf("\n\t---------------------------------------------------------------\n");
		if (cho == 0 || cho == 1)
			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 == 0)
	{
		printf("\n 所以作业已经完成,先来先服务算法模拟结束\n\n");
	}
	else
	{
		printf("\n 所以作业已经完成,高响应比优先算法模拟结束\n\n");
	}
	printf("本组作业的平均周转时间为:%.2f\n", totalTtime / length);
	printf("本组作业的平均带权周转时间为:%.2f\n", totalWtime / length);
	getchar();
	return 0;
}

你可能感兴趣的:(计算机操作系统实验)