进程调度.docx
《进程调度.docx》由会员分享,可在线阅读,更多相关《进程调度.docx(27页珍藏版)》请在冰豆网上搜索。
![进程调度.docx](https://file1.bdocx.com/fileroot1/2023-2/21/f9035527-4369-4dda-8b64-fa4a876200f2/f9035527-4369-4dda-8b64-fa4a876200f21.gif)
进程调度
课题一:
进程调度模拟
1、设计目的
通过对进程调度算法的设计,深入理解进程调度的原理,同时掌握进程调度算法的实现方法和技巧。
2、任务及要求
1.用语言来实现对n个进程采用不同调度算法的进程调度。
2.每个用来标识进程的进程控制块PCB用结构来描述,包括以下字段:
(1)进程优先数ID,其中0为闲逛进程,用户进程的标识数为1,2,3…。
(2)进程优先级Priority,闲逛进程(idle)的优先级为0,用户进程的优先级大于0,且随机产生,优先数越大,优先级越高。
(3)进程占用的CPU时间CPUtime,进程每运行一次,累计值等于4。
(4)进程总共需要运行时间Alltime,利用随机函数产生。
(5)进程状态,0:
就绪态;1:
运行态;2:
阻塞态。
(6)队列指针next,用来将多个进程控制块PCB链接为队列。
3.优先数改变的原则
(1)进程在就绪队列中每呆一个时间片,优先数增加1。
(2)进程每运行一个时间片,优先数减3。
4.在调度前,系统中拥有的进程数PCB_number由键盘输入,经初始化后,所有的进程控制块PCB链接成就绪队列。
3、算法及数据结构
3.1算法的总体思想
先到先服务算法,给每个进程定一个进程号,然后按照进程号顺序进行即可。
最短作业优先算法要判断作业的alltime时间,alltime最小的最先执行,依次按照时间从小到大执行进程。
优先度调度算法,要先判断优先度的大小,优先度最大的先执行,进程运行完毕以后,按照优先数的改变的原则进行改变,然后继续判断所有的优先数的大小,依旧是优先数最大的先执行,直到执行完毕。
RR时间片轮转调度算法,要依次执行时间片用完即阻塞,转交给下一个进程执行,直到所有进程运行完。
3.2数据结构模块
3.2.1功能
进程的结构体声明与函数的声明
3.2.2数据结构
structProcess
{
intPro_Id;//进程编号ID
intPriority;//进程优先级,随机产生
intCPUtime;//进程占用的CPU时间CPUtime
intAlltime;//进程共需运行时间,随机产生
intState;//进程状态
structProcess*Next;
};
/****************函数声明*******************/
intrandom_num();//随机数字产生
structProcess*INITIAL(int*n);//进程的初始化
intprintall(structProcess*P1);//打印所有进程的具体信息
intget_maxpri(structProcess*P1);//获取优先度最高的进程号
intget_mintime(structProcess*P1);//获作业时间最短的进程号
voidalert_status(structProcess*P1,intm);//修改进程的状态
voidalert_pri(structProcess*P1,intm);//修改进程的优先度
voidFCFS(structProcess*Head);//先来先服务算法
voidPriority(structProcess*Head,intn);//优先级调度算法
structProcess*alert_sjf(structProcess*P2,intm);//修改sjf算法状态
voidSJF(structProcess*Head,intn);//SJF调度算法
voidRR(structProcess*Head,intn);//RR时间片调度算法
3.3随机数字产生方法模块
3.3.1功能
随机产生数字,用于进程初始化时的优先度与alltime赋值
3.3.2数据结构
intrandom_num()
3.3.3算法
intrandom_num()
{
intm;
m=rand()%100;
if(m==0)
m=1;
returnm;
}//随机数函数结束
3.4先到先服务(FCFS)模块
3.4.1功能
模拟进程的先到先服务调度算法,按照进程编号依次运行。
3.4.2数据结构
voidFCFS(structProcess*Head);//先来先服务算法
printall(structProcess*Head);//打印所有进程信息
3.4.3算法
voidFCFS(structProcess*Head)
{
structProcess*P1,*P2;
P1=Head;
while(P1!
=NULL)
{
P1->State=1;
//printf("%3d\n",P1->State);
P2=Head;
printall(P2);
printf("按任意键,继续演示.......\n");
getchar();
P1->CPUtime=P1->Alltime;
P1->State=3;
//printf("%3d号进程运行完毕\n",P1->Pro_Id);
//Sleep(1000+P1->Alltime*10);
P1=P1->Next;
}//while
P2=Head;
printall(P2);
printf("演示结束,谢谢。
\n");
}//FCFS结束
3.5SJF(最短作业优先)调度算法模块
3.5.1功能
将每个进程与其下一个CPU区间段相关联。
当CPU为可用时,它会赋给具有最短后续CPU区间的进程。
如果两个进程具有同样长度的CPU区间,那么可以使用FCFS调度来处理。
3.5.2数据结构
voidSJF(structProcess*Head,intn)
intget_mintime(structProcess*P1)
structProcess*alert_sjf(structProcess*P2,intm)
3.5.3算法
/**SJF调度算法**/
voidSJF(structProcess*Head,intn)
{
intm;
inti;
structProcess*P2,*P;
P=NULL;
for(i=0;i{
P2=Head;
m=get_mintime(P2);
printf("\n在未完成的进程中%d号进程需要运行时间最短\n\n",m);
P2=Head;
P=alert_sjf(P2,m);
P2=Head;
printall(P2);
P2=Head;
P->State=3;
P->CPUtime=P->Alltime;
P=NULL;
printf("按任意键,继续演示.......\n");
getchar();
}
P2=Head;
printf("\n所有进程运行结束。
\n\n");
printall(P2);
printf("SJF算法演示完毕,谢谢使用\n");
}
/**获取进程最短时间**/
intget_mintime(structProcess*P1)
{
intk,m;
k=1001;
m=0;
while(P1!
=NULL)
{
if(k>P1->Alltime&&P1->State!
=3)
{
k=P1->Alltime;
m=P1->Pro_Id;
}//if
P1=P1->Next;
}//while
returnm;
}
/**修改sjf算法状态**/
structProcess*alert_sjf(structProcess*P2,intm)
{
structProcess*P1,*P;
intk=0;
P1=P2;
P=NULL;
while
(1)
{
if(P1->Pro_Id==m)
{
P1->State=1;
P=P1;
k=1;
}//if
else
{
P1=P1->Next;
}
if(k==1)
break;
}//while
returnP;
}
3.6优先级调度算法模块
3.6.1功能
1.每个进程被赋予一个优先级数字(优先权)
2.CPU分配给优先权高的进程(优先级数字越小,则优先权越大)
3.6.2数据结构
voidPriority(structProcess*Head,intn)
intget_maxpri(structProcess*P1)
voidalert_pri(structProcess*P1,intm)
voidalert_status(structProcess*P1,intm)
3.6.3算法
/**优先级调度算法**/
voidPriority(structProcess*Head,intn)
{
structProcess*P1,*P2;
intkey=0;
intm;
P1=Head;
P2=Head;
//printf("%d\n",n);
//printf("%d\n",key);
while(key{
m=get_maxpri(P2);//获取优先级最高的进程ID
//printf("%d\n",m);
alert_status(P1,m);//修改进程的运行状态等信息
P2=Head;
if(printall(P2))
key++;
P1=Head;
alert_pri(P1,m);//修改进程的优先级
printf("按任意键,继续演示.......\n");
getchar();
//printf("%d\n",key);
}
printf("所有进程已经全部结束!
!
!
");
key=0;
}
/**获取优先度最高的进程号**/
intget_maxpri(structProcess*P1)
{
intk,m;
k=P1->Priority;
m=P1->Pro_Id;
while(P1->Next!
=NULL)
{
if(kNext->Priority)
{
k=P1->Next->Priority;
m=P1->Next->Pro_Id;
}//if
P1=P1->Next;
}//while
returnm;
}
/**修改进程的优先度**/
voidalert_pri(structProcess*P1,intm)
{
structProcess*P2;
intk;
k=0;
P2=P1;
while(P2!
=NULL)
{
if(P2->Priority>0)
{
if(P2->Pro_Id!
=m)
{
P2->Priority=P2->Priority+1;
}//if
else
{
P2->Priority=P2->Priority-3;
}//else
if(P2->Priority<=0)
{
P2->Priority=0;
P2->State=3;
}//if
}//if
P2=P2->Next;
}//while
}//修改进程优先度函数结束
/**修改进程的状态**/
voidalert_status(structProcess*P1,intm)
{
structProcess*P2;
//intstatus;
P2=P1;
while(P2!
=NULL)
{
if(P2->Pro_Id==m)
{
P2->State=1;
}//if
else
{
if(P2->State==1)
P2->State=2;
}//else
P2=P2->Next;
}//while
}//修改进程状态结束
3.7时间片轮转调度算法模块
3.7.1功能
如果就绪队列中有n个进程,且时间片为q,则每个进程会得到1/n的CPU时间,每个长度不超过q时间单元。
每个进程必须等待CPU的时间不会超过(n-1)q个时间单元,直到它的下一个时间片为止
3.7.2数据结构
voidRR(structProcess*Head,intn)
3.7.3算法
/*****RR时间片调度算法****/
voidRR(structProcess*Head,intn)
{
structProcess*P2,*P1;
intm=n;
P2=Head;
printall(P2);
printf("按任意键,继续演示.......");
getchar();
P2=Head;
P1=Head;
while
(1)
{
while(P1!
=NULL)
{
if(P1->State!
=3)
{
P1->State=1;
printall(P2);
printf("按任意键,继续演示.......\n");
getchar();
P2=Head;
if(P1->CPUtime+4Alltime)
{
P1->State=2;
P1->CPUtime=P1->CPUtime+4;
}
else
{
P1->CPUtime=P1->Alltime;
P1->State=3;
printf("%d号进程已经运行完毕!
!
!
!
\n\n",P1->Pro_Id);
m--;
}//else
}//if
P1=P1->Next;
}//while
if(m==0)
break;
else
P1=Head;
}
P2=Head;
printall(P2);
printf("时间片轮转算法演示结束,谢谢使用。
\n");
}
3.8主函数模块
3.8.1功能
用于程序与用户的交互操作,由用户选择模拟实验的算法,并执行相应的算法。
3.8.2数据结构
intmain()
3.8.3算法
/***********主函数**************/
intmain()
{
structProcess*Head,*P1;
inta;
intk=1;
//intm;
intn;
n=0;
while(k==1)
{
system("cls");
P1=NULL;
Head=NULL;
srand((int)time(NULL));//该语句只需要一次递交种子就可以
printf("**********************实验模拟开始**************************\n");
printf("\n");
printf("\n");
printf("\n");
printf("1.先到先服务调度算法;\n");
printf("2.SJF(最短作业优先)调度算法;\n");
printf("3.优先度调度算法;\n");
printf("4.RR(轮转法)调度算法;\n");
printf("5.退出;\n");
printf("\n");
printf("\n");
printf("\n");
printf("*************************************************************\n");
printf("请输入您的选择:
");
scanf("%d",&a);
while(a!
=1&&a!
=2&&a!
=3&&a!
=4&&a!
=5)
{
printf("对不起,您的选择有误,请重新选择");
scanf("%d",a);
}//while
if(a==1||a==2||a==3||a==4)
{
P1=INITIAL(&n);
Head=P1;
printall(P1);
printf("初始化进程已完成.\n");
printf("\n按任意键实验开始演示:
");
getchar();
getchar();
}
switch(a)
{
case1:
FCFS(Head);
break;
case2:
SJF(Head,n);
break;
case3:
Priority(Head,n);
break;
case4:
RR(Head,n);
break;
case5:
printf("感谢您使用该系统.再见~~\n");
k=0;
break;
}//switch
printf("\n");
printf("\n");
printf("\n");
if(a==1||a==2||a==3||a==4)
{
printf("按任意键回到主菜单....");
getchar();
}
}//while
}//main
3.9进程的初始化模块
3.9.1功能
用于由用户输入进程数以后,对进程的初始化,并利用随机函数,随机生成进程的优先度与alltime,并赋值。
3.9.2数据结构
structProcess*INITIAL(int*n)
3.9.3算法
/**进程的初始化**/
structProcess*INITIAL(int*n)
{
structProcess*P1,*Head,*P2;
inta=0;
inti=0;
P1=P2=Head=NULL;
/**进程的输入**/
do{
printf("pleaseinputPCB_number(请输入进程数):
\n");
scanf("%d",&a);
}while(a==0);//do..while
/**/
P1=(structProcess*)malloc(sizeof(structProcess));
Head=P1;
for(i=1;i<=a;i++)
{
P1->Pro_Id=i;
P1->Priority=random_num();
P1->CPUtime=0;
P1->Alltime=random_num();
P1->State=0;
if(i==a)
{
break;
}
P2=(structProcess*)malloc(sizeof(structProcess));
P1->Next=P2;
P1=P2;
}//for
P1->Next=NULL;
*n=a;
returnHead;
}//初始化函数结束
4、实验结果及分析
4.1实验结果
先到先服务算法演示:
SJF(最短作业优先)调度算法演示:
优先度调度算法演示:
RR(轮转法)调度算法演示:
4.2结果分析
1.intrandom_num()这个函数导致随机数产生以后,所有的随机数都是一个数。
问题原因是:
随机种子是传递给操作系统的,不是传递给函数的,所以,不必多次调用。
在一个程序中,种子只产生一次即可。
也就是说:
srand((int)time(NULL));这句只出现在main函数里一次就可以
修改后运行结果:
2.进程开始执行以后当所有进程都结束后。
程序一直在运行,结束不了。
加入变量key表示已经完成的进程作为解决办法,但是当用指针处理的时候,发现打印出的是key的地址,但是用的是*key,最后只能用printall返回一个值表示有进程完成。
解决了问题,不明白为什么用*key不能打印出
数字而是地址
修改加入变量后结果是:
3.再次选择优先度算法时,运行输入一个进程的时候发现直接没有运行提示程序运行完毕
原因是第一次运行完成后,没有把key置0导致第二次运行的时候出现key==n,不执行while循环。
修改后执行: