一、 实验目的
用高级语言编写和调试一个或多个作业调度的模拟程序,以加深对作业调度算法的理解。
二、 实验内容
1. 写并调试一个单道处理系统的作业等待模拟程序。
2. 作业等待算法:分别采用先来先服务(FCFS)、响应比高者优先(HRN)的调度算法。
3. 由于在单道批处理系统中,作业一投入运行,它就占有计算机的一切资源直到作业完成为止,因此调度作业时不必考虑它所需要的资源是否得到满足,它所占用的 CPU时限等因素。
4. 每个作业由一个作业控制块JCB表示,JCB可以包含如下信息:作业名、提交时间、所需的运行时间、所需的资源、作业状态、链指针等等。作业的状态可以是等待W(Wait)、运行R(Run)和完成F(Finish)三种状态之一。每个作业的最初状态总是等待W。
5. 对每种调度算法都要求打印每个作业开始运行时刻、完成时刻、周转时间、带权周转时间,以及这组作业的平均周转时间及带权平均周转时间。
三、实现思路
通过自己编写一个文件并键入作业信息,程序读取文件信息计算长度,之后连接好链表并将文件信息(包括文件名,运行时间,到达时间)存入存储链表;然后在循环中调用检查函数每次显示正在运行的进程和等待进程,同时将已到达的进程放入另一个可运行链表;同时对可运行链表运行执行进程,将运行完的进程放入结构数组存储,接着调用排序函数,最后链表指向下一项,该循环运行直到到达链表结尾;最后,调用显示函数显示要求的信息。高响应比
通过自己编写一个文件并键入作业信息,程序读取文件信息计算长度,之后连接好链表并将文件信息(包括文件名,运行时间,到达时间,优先级)存入存储链表;这了的优先级在两个作业同时到达时起作用。然后在循环中调用检查函数每次显示正在运行的进程和等待进程,将运行完的进程放入结构数组存储,接着调用排序函数,最后链表指向下一项,该循环运行直到到达链表结尾;最后,调用显示函数显示要求的信息。 先来先服务
四、主要的数据结构
结构链表,txt文件。
struct pcb /* 定义进程控制块PCB */
{
char name[namelen];
char state; // 状态
double super; // 优先级
int ntime; // 需要运行时间
int rtime; // 实际运行时间
int betime;// 开始时间
int fintime;//结束时间
int artime; //到达时间
int in; //是否在可运行链表中
struct pcb * link; // 链指针
}; // 高响应比
struct JCB /* 定义进程控制块JCB */
{
char name[namelen];
char state; // 状态
int ntime; // 需要运行时间
int rtime; // 实际运行时间
int betime;// 开始时间
int fintime;//结束时间
int artime; //到达时间
struct JCB * link; // 链指针
};// 先来先服务
五、代码:
先来先服务:
// HRRN algorithm
#include
#include
#include
#define namelen 10
#define bufsize 20
struct JCB /* 定义进程控制块PCB */
{
char name[namelen];
char state; // 状态
int ntime; // 需要运行时间
int rtime; // 实际运行时间
int betime;// 开始时间
int fintime;//结束时间
int artime; //到达时间
struct JCB * link; // 链指针
};
int link ( struct JCB * jcblist, int len)
{
int i;
jcblist[len].link = NULL;
for ( i = len; i > 0; i--)
jcblist[i-1].link = &jcblist[i];
return 1;
}
int check ( struct JCB * jcblist, int *curtime )
{
struct JCB * temp;
while ( jcblist->link != NULL )
{
if ( jcblist->artime > *curtime ) // no arrived jobs
{
printf ("No arrived jobs.\n");
return 0;
}
else
{
printf ( "The executing job:%s\n", jcblist->name);
break;
}
jcblist = jcblist->link;
}
temp = jcblist+1;
if ( temp->artime > *curtime )
{
printf ( "No jobs in waiting queue.\n");
return 0;
}
else
{
printf ( "In waiting queue:\n");
while ( temp->artime <= *curtime && temp->link != NULL )
{
disp( temp );
temp = temp->link;
}
}
return 1;
}
int sort ( struct JCB * jcblist ) // insertion sort
{
int i, j, pl = 0;
for ( ; jcblist[pl].link != NULL && jcblist[pl].link->ntime != 0; pl++ )
; // the length of the current jcblist
if ( pl == 0 || pl == 1)
{
printf ( "Nothing!\n");
return 0;
}
struct JCB * temp = (struct JCB *)malloc( sizeof( struct JCB));
for ( i = 1; i < pl && jcblist[i].ntime != 0; i++ ) // use insertion sort
{
j = i;
strcpy(temp->name, jcblist[i].name),
temp->ntime = jcblist[i].ntime,temp->artime = jcblist[i].artime ;
while ( j > 0 && temp->artime < jcblist[j-1].artime )
{
strcpy(jcblist[j].name, jcblist[j-1].name),
jcblist[j].ntime = jcblist[j-1].ntime,jcblist[j].artime = jcblist[j-1].artime ;
j--;
}
strcpy(jcblist[j].name, temp->name),
jcblist[j].ntime = temp->ntime, jcblist[j].artime = temp->artime;
}
free ( temp );
return 1;
}
int running ( struct JCB * p, struct JCB store[], int * arrlen, int * curtime )
{
printf ( "running...\n");
if ( p->rtime == 0 )
p->betime = *curtime;
while ( p->rtime < p->ntime )
p->rtime = p->rtime + 1, *curtime = *curtime + 1; // 运行时间
if ( p->rtime == p->ntime ) // 运行时间等于需要时间
{
p->state = 'F', p->fintime = *curtime;
strcpy(store[*arrlen].name, p->name), store[*arrlen].ntime = p->ntime;
store[*arrlen].rtime = p->rtime, store[*arrlen].state = p->state;
store[*arrlen].betime = p->betime;
store[*arrlen].fintime = p->fintime, store[*arrlen].artime = p->artime;
*arrlen = *arrlen+1;
printf ( "Job:%s finished.\n\n\n", p->name);
}
return 1;
}
int disp ( struct JCB * pr)
{
printf(" qname \t state \t ndtime \n");
printf(" |%s\t", pr->name);
printf(" |%c\t", pr->state);
printf(" |%d\t", pr->ntime);
printf("\n");
return 1;
}
int showresult ( struct JCB * store, int pcblen )
{
int arrlen;
double tatime = 0.0, tatimewe = 0.0;
for ( arrlen = 0; arrlen < pcblen; arrlen++ )
{
printf("\n qname \t state \t ndtime btime \t endtime runtime artime 周转时间 带权周转时间\n");
printf(" |%s\t", store[arrlen].name);
printf(" |%c\t", store[arrlen].state);
printf(" |%d\t", store[arrlen].ntime);
printf(" |%d\t", store[arrlen].betime);
printf(" |%d\t", store[arrlen].fintime);
printf(" |%d\t", store[arrlen].rtime);
printf(" |%d\t", store[arrlen].artime);
printf(" |%d\t", store[arrlen].fintime - store[arrlen].artime);
printf(" |%f\t", (double)( store[arrlen].fintime - store[arrlen].artime )/ store[arrlen].ntime);
printf("\n");
tatime += store[arrlen].fintime - store[arrlen].artime;
tatimewe +=( store[arrlen].fintime - store[arrlen].artime )/ store[arrlen].ntime;
}
printf ( "\n平均周转时间 \t 带权周转时间\n");
printf ( "|%f\t", tatime / pcblen );
printf ( "|%f\t", tatimewe / pcblen);
}
int main ( void )
{
int i, j = 0, pcbnum = 0, curtime = 0, arrlen = 0;// job's number, current time store array's length counter
int pcblen = 0, filechar;// arrlen: the length of store
char * buffer = (char *)malloc( sizeof(char) * bufsize); // the buffer
FILE * infor = fopen( "test.txt", "r");
while ( (filechar = fgetc(infor)) != EOF)
if ( filechar == '\n')
pcblen++;
pcblen += 1; // get the length of the file.
struct JCB * jcblist = (struct JCB *)malloc( sizeof ( struct JCB)* pcblen);// allocate memory for the jobs
struct JCB * store = (struct JCB *)malloc( sizeof ( struct JCB)* pcblen); // store list
struct JCB * location1 = (struct JCB *)malloc(sizeof ( struct JCB));
location1 = jcblist;
link ( jcblist, pcblen);// link the pcblist arrpcb
rewind( infor );
// file information assignment
while ( fgets(buffer, bufsize, infor) != NULL )
{
for ( i = 0; buffer[i] != ' '; i++ ) // name assignment
jcblist[pcbnum].name[i] = buffer[i];
jcblist[pcbnum].name[i] = '\0';
jcblist[pcbnum].ntime = atoi(buffer + i); // ntime assignment
i++;
for ( ; buffer[i] != ' '; i++ )
;
jcblist[pcbnum].artime = atoi( buffer + i);
jcblist[pcbnum].state = 'W', jcblist[pcbnum].rtime = 0;
pcbnum++;
}
sort ( jcblist );
while ( j < pcblen )
{
printf ( "Current time:%d\n", curtime);
check ( jcblist + j, &curtime ); // the header of arrpcb
running( jcblist+j, store, &arrlen, &curtime ); // also calculate the super
j++;
}
printf("\n\n All jobs have finished.\n");
showresult ( store, pcblen );
fclose( infor );
free ( location1 ), free( store );
return 0;
}
高响应比:
// HRRN algorithm
#include
#include
#include
#define namelen 10
#define bufsize 20
struct pcb /* 定义进程控制块PCB */
{
char name[namelen];
char state; // 状态
double super; // 优先级
int ntime; // 需要运行时间
int rtime; // 实际运行时间
int betime;// 开始时间
int fintime;//结束时间
int artime; //到达时间
int in; //是否在可运行链表中
struct pcb * link; // 链指针
};
int link ( struct pcb * pcblist, int len)
{
int i;
pcblist[len].link = NULL;
for ( i = len; i > 0; i--)
pcblist[i-1].link = &pcblist[i];
return 1;
}
int check ( struct pcb * pcblist, struct pcb * arrpcb, int *curtime, int * arrpcblen, int * j )
{
int plco = 0, i = *j;// i record the current loc
while ( pcblist[plco].link != NULL ) // put the arrived jobs into arrpcb
{
if ( pcblist[plco].in == 0 && pcblist[plco].artime <= *curtime && pcblist[plco].link != NULL)
{
arrpcb[*arrpcblen].ntime = pcblist[plco].ntime, strcpy(arrpcb[*arrpcblen].name, pcblist[plco].name);
arrpcb[*arrpcblen].state = 'W', *arrpcblen = *arrpcblen + 1;
pcblist[plco].in = 1, arrpcb[*arrpcblen].artime = pcblist[plco].artime;
}
plco++;
}
if ( arrpcb[i].ntime == 0 )
{
printf ( "No arrive jobs!\n");
return 0;
}
struct pcb * temppcb2 = arrpcb->link; // calculate the super
while (temppcb2->link != NULL && temppcb2->ntime != 0)
{
temppcb2->super = ((double)*curtime - (double)(temppcb2->artime)) / ( ((double)*curtime - (double)(temppcb2->artime)) + temppcb2->ntime);// 完成一个任务后更新优先级;
temppcb2 = temppcb2->link;
}
sort(arrpcb + i);
printf ( "\n The execute job :\n");
arrpcb[i].state = 'R';// change the running job's state
disp( arrpcb+i );
struct pcb * temppcb1; // show the waiting queue
temppcb1 = arrpcb[i].link;
if ( temppcb1->link != NULL && temppcb1->ntime != 0 ) // show the jobs in the waiting queue
printf("\n The jobs in waiting queue:\n");
while ( temppcb1->link != NULL && temppcb1->ntime != 0 )
{
disp ( temppcb1 );
temppcb1 = temppcb1->link;
}
return 1;
}
int sort ( struct pcb * arrpcb ) // insertion sort
{
int i, j, pl = 0;
for ( ; arrpcb[pl].link != NULL && arrpcb[pl].link->ntime != 0; pl++ )
; // the length of the current arrpcb
if ( pl == 0 || pl == 1)
return 0;
//printf ( "The current of the list:%d\n", pl);
struct pcb * temp = (struct pcb *)malloc( sizeof( struct pcb));
for ( i = 1; i < pl && arrpcb[i].ntime != 0; i++ ) // use insertion sort
{
j = i;
temp->super = arrpcb[i].super, strcpy(temp->name, arrpcb[i].name),
temp->ntime = arrpcb[i].ntime;
while ( j > 0 && temp->super > arrpcb[j-1].super )
{
arrpcb[j].super = arrpcb[j-1].super, strcpy(arrpcb[j].name, arrpcb[j-1].name),
arrpcb[j].ntime = arrpcb[j-1].ntime;
j--;
}
arrpcb[j].super = temp->super, strcpy(arrpcb[j].name, temp->name),
arrpcb[j].ntime = temp->ntime;
}
free ( temp );
return 1;
}
int running ( struct pcb * p, struct pcb store[], int * arrlen, int * curtime )
{
if ( p->rtime == 0 )
p->betime = *curtime;
while ( p->rtime < p->ntime )
p->rtime = p->rtime + 1, *curtime = *curtime + 1; // 运行时间
if ( p->rtime == p->ntime ) // 运行时间等于需要时间
{
p->state = 'F', p->fintime = *curtime;
strcpy(store[*arrlen].name, p->name), store[*arrlen].ntime = p->ntime;
store[*arrlen].rtime = p->rtime, store[*arrlen].state = p->state;
store[*arrlen].super = p->super, store[*arrlen].betime = p->betime;
store[*arrlen].fintime = p->fintime, store[*arrlen].artime = p->artime;
*arrlen = *arrlen+1;
printf ( "Job:%s finished.\n", p->name);
}
return 1;
}
int disp ( struct pcb * pr)
{
printf(" qname \t state \t ndtime \n");
printf(" |%s\t", pr->name);
printf(" |%c\t", pr->state);
printf(" |%d\t", pr->ntime);
printf("\n");
return 1;
}
int showresult ( struct pcb * store, int pcblen )
{
int arrlen;
double tatime = 0.0, tatimewe = 0.0;
for ( arrlen = 0; arrlen < pcblen; arrlen++ )
{
printf("\n qname \t state \t ndtime btime \t endtime runtime artime 周转时间 带权周转时间\n");
printf(" |%s\t", store[arrlen].name);
printf(" |%c\t", store[arrlen].state);
printf(" |%d\t", store[arrlen].ntime);
printf(" |%d\t", store[arrlen].betime);
printf(" |%d\t", store[arrlen].fintime);
printf(" |%d\t", store[arrlen].rtime);
printf(" |%d\t", store[arrlen].artime);
printf(" |%d\t", store[arrlen].fintime - store[arrlen].artime);
printf(" |%f\t", (double)( store[arrlen].fintime - store[arrlen].artime )/ store[arrlen].ntime);
printf("\n");
tatime += store[arrlen].fintime - store[arrlen].artime;
tatimewe +=( store[arrlen].fintime - store[arrlen].artime )/ store[arrlen].ntime;
}
printf ( "\n平均周转时间 \t 带权周转时间\n");
printf ( "|%f\t", tatime / pcblen );
printf ( "|%f\t", tatimewe / pcblen);
}
int main ( void )
{
int i, j = 0, pcbnum = 0, curtime = 0, arrlen = 0;// job's number, current time store array's length counter
int pcblen = 0, filechar, arrpcblen = 0;// arrlen: the length of store
char * buffer = (char *)malloc( sizeof(char) * bufsize); // the buffer
FILE * infor = fopen( "test.txt", "r");
while ( (filechar = fgetc(infor)) != EOF)
if ( filechar == '\n')
pcblen++;
pcblen += 1; // get the length of the file.
struct pcb * pcblist = (struct pcb *)malloc( sizeof ( struct pcb)* pcblen);// allocate memory for the jobs
struct pcb * store = (struct pcb *)malloc( sizeof ( struct pcb)* pcblen); // store list
struct pcb * arrpcb = (struct pcb *)malloc( sizeof ( struct pcb)* pcblen); // arrived jobs
struct pcb * location1 = (struct pcb *)malloc(sizeof ( struct pcb));
struct pcb * location2 = (struct pcb *)malloc(sizeof ( struct pcb));
memset( arrpcb, 0, sizeof(struct pcb) * pcblen );
location1 = pcblist, location2 = pcblist;
link ( pcblist, pcblen), link ( arrpcb, pcblen);// link the pcblist arrpcb
rewind( infor );
// file information assignment
while ( fgets(buffer, bufsize, infor) != NULL )
{
for ( i = 0; buffer[i] != ' '; i++ ) // name assignment
pcblist[pcbnum].name[i] = buffer[i];
pcblist[pcbnum].name[i] = '\0';
pcblist[pcbnum].ntime = atoi(buffer + i); // ntime assignment
i++;
for ( ; buffer[i] != ' '; i++ )
;
pcblist[pcbnum].artime = atoi( buffer + i);
pcblist[pcbnum].state = 'W', pcblist[pcbnum].rtime = 0;
pcblist[pcbnum].super = 1.0, pcblist[pcbnum].in = 0;
pcbnum++;
}
while ( j < pcblen )
{
printf ( "\nCurrent time:%d", curtime);
check ( pcblist, arrpcb, &curtime, &arrpcblen, &j ); // the header of arrpcb
running( arrpcb + j, store, &arrlen, &curtime );// also calculate the super
sort(arrpcb+j+1);
j++;
i = 0;
}
printf("\n\n All jobs have finished.\n");
showresult ( store, pcblen );
free ( location1 ), free( location2 ), free( store );
return 0;
}
对比:
高响应比:结构体较为复杂,代码实现较为复杂,思路也相对复杂一些,每次运行完需要更新每个作业的优先级别,运行时间相对会多一些。(例子中数据比较少,因此区别不大)
同时,很明显,平均周转时间和带权周转时间相对小。
先到先服务:结构体相对简单,代码简单些,只需要一次排序(代码中对同一时间到达的作业按输入顺序执行)。运行时间较短。最后,平均周转时间和带权周转时间相对较大。
总结:从运行结果可以看出,对于不多的输入数据,高响应比和先到先服务对作业的调度时间相差不大;但对于较多的输入数据,高响应比会比先到先服务的调度时间少。同时,高响应比作业调度方面因为是动态优先级会比先到先得更加合理。