2 minutes
进程调度模拟
一.实验目的****
1.理解进程调度的算法
2、利用数据结构中的常见结构来模拟进程调度过程
二.实验内容****
设计一个按优先数调度算法实现处理器调度的进程。
(1) 假定系统有五个进程,每一个进程用一个进程控制块PCB 来代表。进程控制块的格式为:
其中,
进程名—-作为进程的标识,假设五个进程的进程名分别是P1,P2,P3,P4,P5。
指针—-按优先数的大小把五个进程连成队列,用指针指出下一个进程的进程控制块
首地址,最后一个进程中的指针为“0”。
要求运行时间—-假设进程需要运行的单位时间数。
优先数—-赋予进程的优先数,调度时总是选取优先数大的进程先执行。
状态—-可假设有两种状态,“就绪”状态和“结束“状态,五个进程的初始状态都为“就绪
“状态,用“R”表示,当一个进程运行结束后,它的状态变为“结束”,用“E”表示。
(2) 在每次运行你所设计的处理器调度程序之前,为每个进程任意确定它的“优先数”和“要求
运行时间”。
(3) 为了调度方便,把五个进程按给定的优先数从大到小连成队列,用一单元指出队首进程,用
指针指出队列的连接情况。例:
队首标志
(4) 处理器调度总是选队首进程运行。采用动态改变优先数的办法,进程每运行一次优先数就减
“1”。由于本实验是模拟处理器调度,所以,对被选中的进程并不实际的启动运行,而是执行:
优先数-1
要求运行时间-1
来模拟进程的一次运行。
提醒注意的是:在实际的系统中,当一个进程被选中运行时,必须恢复进程的现场,它占有
处理器运行,直到出现等待事件或运行结束。在这里省去了这些工作。
(5) 进程运行一次后,若要求运行时间≠0,则再将它加入队列(按优先数大小插入,且置队首
标志);若要求运行时间=0,则把它的状态修改为“结束”(),且退出队列。
(6) 若“就绪”状态的进程队列不为空,则重复上面(4)和(5)的步骤,直到所有进程都成为
“结束”状态。
(7) 在所设计的称序中应有显示或打印语句,能显示或打印每次被选中进程的进程名以及运行一
次后进称对列的变化。
(8) 为五个进程任意确定一组“优先数”和“要求运行时间”,启动所设计的处理器调度程序,
显示或打印逐次被选中进程的进程名以及进程控制块的动态变化过程。
#include “stdio.h”
struct pcb /*进程控制块结构体*/
{char name[3]; /*进程标识符*/
char number[3]; /*进程优先数*/
char status[2]; /*进程状态:0-就绪*/
struct pcb *next; /*指向后一进程的指针*/
struct pcb *prior;/*指向前一进程的指针*/
}stu;
struct pcb *fir; /*进程链表的头指针*/
struct pcb *back; /*进程链表的尾指针*/
void enter( ),delete( ),prin( );
char str[12][3]={“a”,”2″,”0″,”b”,”10″,”0″,”c”,”30″,”0″,”d”,”35″,”0″};
main( )
{
fir=back=NULL; /*对进程链表的头尾指针赋初值*/
enter(0); /*对进程链表赋初值*/
for(;;)
{switch(menu( )){
case 1 : enter(1); break; /*插入或初始化*/
case 2 : delete( ); break; /*删除*/
case 3 : prin( ); break; /*显示*/
case 4 : exit(0);
}
}
}
/*主菜单*/
menu( )
{
char ch[2];
int n;
printf(“\t就绪队列操作,请选择功能:\n”);
printf(“\t1.插入进程的信息\n”);
printf(“\t2.删除进程的信息\n”);
printf(“\t3.显示进程链表内容\n”);
printf(“\t4.退出\n”);
do{
printf(“\n\t请按数字选择:”);
gets(ch);
n=atoi(ch);
}while(n<0 || n>4);
return(n);
}
void enter(int q)
{
int qq;
struct pcb *inf,*bc( );
if(q==1)
{
inf=(struct pcb *)malloc(sizeof(stu)); /*开辟新结点*/
if(!inf){
printf(“\tuse up!\n”);
return;
}
inputs(“\t请输入进程标识符(最多两位):”,inf->name,2);
inputs(“\t请输入进程优先数(最多两位):”,inf->number,2);
inputs(“\t请输入进程当前状态(一位):”,inf->status,1);
fir=bc(inf,fir); /*插入新结点*/
}
else
{for(qq=0;qq<4;qq++) /*结点初始化*/
{inf=(struct pcb *)malloc(sizeof(stu));
if(!inf){
printf(“\tuse up!\n”);
return;
}
strcpy(inf->name,str[qq*3]);
strcpy(inf->number,str[qq*3+1]);
strcpy(inf->status,str[qq*3+2]);
fir=bc(inf,fir);
}
}
}
inputs(sm,s,count)
char *sm,*s;
int count;
{
char q[3];
do{
printf(sm); /*打印提示信息*/
gets(q);
if(strlen(q)>count) printf(“\t太长了!\n”); /*输入长度判断*/
}
while(strlen(q)>count);
strcpy(s,q); /*把输入内容放入结构中*/
}
struct pcb *bc(i,st)
struct pcb *i;
struct pcb *st;
{
struct pcb *j,*k;
if(atoi(i->status)==0) /*判断进程状态是否就绪*/
{
if(back==NULL) /*链表为空时的插入*/
{
i->next=NULL;
i->prior=NULL;
back=i;
return(i);
}
j=st; /*令J指向链表的头*/
while(j)
{if(strcmp(j->name,i->name)==0) /*进程标识符要唯一*/
{printf(“\n\t该进程已存在就绪队列中。\n\n”);
return(st);
}
j=j->next;
}
j=st;
k=NULL;
while(j){
if(atoi(j->number)<atoi(i->number)) /*判断进程优先数,找到要插入的位置*/
{
k=j;
j=j->next;
}
else
{
if(j->prior) /*判断J是否为头指针*/
{
j->prior->next=i; /*在链表的中间插入*/
i->next=j;
i->prior=j->prior;
j->prior=i;
return(st);
}
i->next=j; /*在链表的头插入*/
i->prior=NULL;
j->prior=i;
return(i);
}
}
k->next=i; /*在链表的尾插入*/
i->next=NULL;
i->prior=k;
back=i;
return(st);
}
printf(“\n\t该进程不是就绪状态,不能插入就绪队列中。\n\n”);
return(st);
}
void delete( )
{
struct pcb *in;
char s[2];
printf(“\t请输入进程标识符:”);
gets(s);
in=fir;
while(in){
if(strcmp(s,in->name)==0) break; /*寻找要删除的进程*/
else in=in->next;
}
if(in==NULL)
printf(“\t未找到此进程!\n”);
if(in){ /*找到进程*/
if(fir==in) /*该进程为链表头时*/
{
fir=in->next;
if(fir) fir->prior=NULL; /*该链表删除进程结点后不为空*/
else back=NULL;
}
else{
in->prior->next=in->next;
if(in!=back) /*该进程不在链表尾*/
in->next->prior=in->prior;
else back=in->prior;
}
free(in); /*释放进程空间*/
}
}
void prin( )
{
struct pcb *j;
j=fir;
while(j){ /*显示所有进程的信息*/
printf(“\t%s “,j->name);
printf(“\t%s “,j->number);
printf(“\t%s “,j->status);
printf(“\n”);
j=j->next;
} }
341 Words
2019-11-21 00:00