作业调度算法 先来先服务FCFS调度算法
- 作业调度的原理:
非抢占调度
把作业从外存调入内存 - 作业调度算法:
先来先服务FCFS 短作业优先SJF 静态优先级调度 高响应比优先调度 - 实验原理
作业调度算法:采用先来先服务(FCFS)调度算法
,即按作业提交的/到达的(到达后备队列的时间)先后次序进行调度
。从外存后备队列
中选择几个最先进入该队列的作业,总是首先调度最先到达(可以理解为在系统中等待时间越长,优先级越高
)的作业进入内存,为他们分配资源、创建进程,然后再放入就绪队列
。 每个作业由一个作业控制块JCB表示,JCB可以包含如下信息:作业名、提交时间、所需的运行时间
、作业状态等等。
作业的状态可以是等待W(Wait)、运行R(Run)和完成F(Finish)三种状态之一。每个作业的最初状态总是等待W。 各个等待的作业按照提交时刻的先后次序排队
,总是首先调度等待队列中队首的作业。
每个作业完成后要输出该作业的开始运行时刻、完成时刻、周转时间和带权周转时间,这一组作业完成后计算并输出这组作业的平均周转时间、平均带权周转时间。
2)SJF调度算法:在提交时间相同(已到达外存作业后备队列的)时,按作业估计运行时间的长短进行调度。
- 以下为实验:先来先服务(FCFS)调度算法
周转时间 = 完成时间 - 提交时间
或周转时间 = 运行时间 + 等待时间
带权周转时间 = 周转时间 / 运行时间
#include<stdio.h>
#include<stdlib.h>
//操作系统实验:(作业调度算法)先来先服务FCFS调度算法
typedef struct JCB {
int id;//作业序号
char state;//当前作业状态
int at;//作业提交时间
int rt;//作业运行时间
int st;//作业开始时间
int ft;//作业完成时间
float zt;//周转时间
float dt;//带权周转时间
struct JCB* next;
}*work, jcb;
jcb* creatwork(int x, int y, int z) {
work newwork = (work)malloc(sizeof(jcb));
newwork->id = x;
newwork->state = 'W';
newwork->at = y;
newwork->rt = z;
newwork->st = 0;
newwork->ft = 0;
newwork->dt = 0.00f;
newwork->zt = 0.00f;
newwork->next = NULL;
return newwork;
}
void delwork(jcb *n, int x) { //删除作业已经完成了的结点
work d;
if (n != NULL) {
while (n->next->id != x) {
n = n->next;
}
d = n->next;
n->next = d->next;
free(d);
}
}
float zt = 0, dt = 0; //zt用于记录总周转时间,dt记录总带权周转时间
void disp(jcb* q1) /*建立作业显示函数,用于显示当前作业*/
{
printf("\n id \t state \t at \t rt \t st \t ft \t zt \t dt \n");
printf("|%d\t", q1->id); // 格式输出的问题,之前用(int数据)以%s输出,导致了程序中断
printf("|%c\t", q1->state);
printf("|%d\t", q1->at);
printf("|%d\t", q1->rt);
printf("|%d\t", q1->st);
printf("|%d\t", q1->ft);
printf("|%f\t", q1->zt);
printf("|%f\t", q1->dt);
printf("\n该作业周转时间为 %.0f \n", q1->zt);
zt += q1->zt;
printf("该作业带权周转时间为 %.2f \n", q1->dt);
dt += q1->dt;
printf("\n");
}
void count(jcb* point, int num) {
jcb *q, *p;//q用于记录最先提交的作业位置及当前作业,p用于遍历链表
float time = 0, _num = num; //time记录当前时间,建个作业数目的变量副本_num
jcb* p1 = point;
while (_num != 0) {
p = point->next;
q = p;
//循环排序 按提交时间
while (p != NULL) {
if (p->at < q->at) {
q = p;
}
p = p->next;
}
printf("当前执行的作业序号为 work%d", q->id);
if (time <= q->at) {
q->state = 'R';
q->st = q->at;
time = q->rt + q->at;
}
else {
q->state = 'R';
q->st = time;
time = time + q->rt;
q->ft = time;
}
//保存信息
q->zt = time - q->at;
q->dt = (time - q->at) / q->rt;
//正在运行的作业显示输出
disp(q);
/* //其他状态的作业显示输出 没成功 如你有好的思路可以留言探讨
while(p1 != NULL)
{
if (p1 == q)
break;
else
disp(p1);
p1 = p1->next;
}*/
delwork(point, q->id);
--_num;
}
printf("\n");
printf("平均周转时间为 %.2f \n", zt / num);
printf("平均带权周转时间为 %.2f \n", dt / num);
}
int main() {
int n, i, y, z;
work tail = NULL;
work head = NULL;
printf("请输入作业数量:");
scanf_s("%d", &n);
tail = (work)malloc(sizeof(jcb));
head = tail;
for (i = 1; i <= n; i++) {
printf("请输入work%d号作业的提交时间、运行时间:", i);
scanf_s("%d%d", &y, &z);
tail->next = creatwork(i, y, z);
tail = tail->next;
}
count(head, n);
system("pause");
return 0;
}
实验室代码:
#include "stdio.h"
#include <stdlib.h>
#include <conio.h>
#define getpch(type) (type*)malloc(sizeof(type))
#define NULL 0
//FCFS 先来先服务算法2
//定义作业jcb结构体
struct jcb
{
char name[100];
char state;
int tr;//作业提交时间
int tn;//作业运行时间
int ts;//作业开始时间
int tf;//作业完成时间
float ti;//作业周转时间
float wi;//作业带权周转时间
struct jcb* link;
}*ready=NULL,*h,*p;
typedef struct jcb JCB;
int time= 0;
int num = 0; //作业数量
//JCB *channel[100];
//fcfs算法实现
void sort() /* 建立对作业进行提交时间排列函数*/
{
JCB *first, *second;
int insert=0;
if((ready==NULL)||((p->tr)<(ready->tr))) /*提交时间最小者,插入队首*/
{
p->link=ready;
ready=p;
}
else /* 进程比较提交时间,插入适当的位置中*/
{
first=ready;
second=first->link;
while(second!=NULL)
{
if((p->tr)<(second->tr)) /*若插入作业比当前作业提交时间小,*/
{
/*插入到当前进程前面*/
p->link=second;
first->link=p;
second=NULL;
insert=1;
}
else /* 插入进程提交时间最高,则插入到队尾*/
{
first=first->link;
second=second->link;
}
}
if(insert==0) first->link=p;
}
}
void input() /* 建立作业控制块函数*/
{
int i;
//clrscr(); /*清屏*/
printf("\n 请输入作业数量?");
scanf("%d",&num);
for(i=0; i<num; i++)
{
printf("\n 作业号No.%d:\n",i);
p=getpch(JCB);
printf("\n 输入作业名:");
scanf("%s",p->name);
printf("\n 输入作业提交时间:");
scanf("%d",&p->tr);
printf("\n 输入作业运行时间:");
scanf("%d",&p->tn);
printf("\n");
p->ts=0;
p->tf=0;
p->ti=0.0f;
p->wi=0.0f;
p->state='w';
p->link=NULL;
sort(); /* 调用sort函数*/
}
}
int space()
{
int l=0;
JCB* pr=ready;
while(pr!=NULL)
{
l++;
pr=pr->link;
}
return(l);
}
void destroy() /*建立作业撤消函数(进程运行结束,卸载作业)*/
{
printf("\n 作业[%s] 已完成.\n",p->name);
free(p);
}
void running() /* 建立作业就绪函数(作业运行时间到,置就绪状态*/
{
if(p->link==NULL)
destroy(); /* 调用destroy函数*/
}
void disp(JCB * pr) /*建立作业显示函数,用于显示当前作业*/
{
printf("\n jname \t state \t tr \t tn \t ts \t tf \t ei \t wi \n");
printf("|%s\t",pr->name);
printf("|%c\t",pr->state);
printf("|%d\t",pr->tr);
printf("|%d\t",pr->tn);
printf("|%d\t",pr->ts);
printf("|%d\t",pr->tf);
printf("|%f\t",pr->ti);
printf("|%f\t",pr->wi);
printf("\n");
}
void check() /* 建立作业查看函数 */
{
JCB* pr;
printf("\n **** 当前正在运行的作业是:%s",p->name); /*显示当前运行作业*/
//累加变量time 记录当前用时 !!!
if(time >= p->tr)
{
p->ts=time;
p->tf=p->ts+p->tn;
time = p->tf;
}
else
{
p->ts=p->tr;
p->tf=p->ts+p->tn;
time= p->tf;
}
p->ti = p->tf - p->tr;
p->wi = p->ti / p->tn;
//!!!
disp(p);
pr=ready;
printf("\n ****当前就绪队列状态为:\n"); /*显示就绪队列状态*/
while(pr!=NULL)
{
disp(pr);
pr=pr->link;
}
}
int main() /*主函数*/
{
int len,h=0;
float eti=0.0;
float ewi=0.0;
char ch;
input();
len=space();
while((len!=0)&&(ready!=NULL))
{
ch=getchar();
h++;
printf("\n The execute number:%d \n",h);
p=ready;
ready=p->link;
p->link=NULL;
p->state='R';
check();
//保存信息
eti+=p->ti;
ewi+=p->wi;
running();
printf("\n 按任一键继续......");
ch=getchar();
}
printf("\n\n 作业已经完成.\n");
ch=getchar();
eti/= num;
ewi/= num;
printf("\n该组作业平均周转时间为:%0.2f",eti);
printf("\n该组作业平均带权周转时间为:%0.2f",ewi);
return 0;
}
实验运行截图: