程序下载链接:https://download.csdn.net/download/m0_56241309/86945709
进程调度模拟
摘要:进程调度是操作系统中必不可少的一种调度,在3中OS中都无一例外地配置了进程调度。此外,它也是对系统性能影响最大的一种处理机调度,在操作系统中具有十分重要的地位。本次模拟,旨在全方位地了解、掌握、运用各种调度算法,包括从本质上理解各种调度方法的实现方式、各种调度算法使用的数据结构、各种调度方法使用的函数模块、各种调度算法的函数调用情况等等。针对本次模拟,任务中包括了四种在操作系统中较为重要的调度方法,因此最先考虑的是如何依次实现各种调度方法,包括对各种算法的系统功能设计、模块、流程设计、数据结构设计等等。之后再依调整各种算法内部的数据结构以及符号名,消除各个算法之间的冲突,主要是命名冲突引起的函数调用冲突、变量使用冲突。在对各种算法进行调整后,将其整合到一个主体呈现出switch结构的MAIN()函数中。经过本次模拟,总体上较为完整地实现了对N个进程采用4个进程调度算法的目的(四选一),但在各种算法的内部仍然存在许多值得优化的地方,例如在MAIN()函数中涉及一个整体的数据结构即可避免在每一个算法中都对数据结构进行大体上重复的定义,诸如此类的可以优化的地方依然存在,因此本次模拟并不是最终目的,后继学习过程中对操作系统调度算法的更加熟练的掌握将更加有助于我们对于计算机操作系统的理解与掌握。
关键词:操作系统;进程调度;课程设计
1 设计任务
1.1 设计目的
在多道程序环境下,内存中存在许多进程,其数目往往多余处理及的数量。这就要求操作系统能够按照某种算法动态地将处理机分配给处于就绪状态的进程。对于一个大型的操作系统而言,其运行是的性能,诸如系统吞吐量、资源利用率、作业周转时间、响应的及时性等,在很大程度上都取决于处理机调度性能的好坏。如若处理机调度存在问题,则会非常容易导致系统出现死锁,进程将无法向前推进。次模拟选题为进程调度模拟,旨在了解、认识、掌握调度算法这一处理机调度最为核心的部分,实现对多个进程实现不同的调度方法,加深对操作系统调度方法的掌握,进而更加深层次地认识操作系统。
1.2 设计内容
1.2.1设计要求
(1)对N个进程分别采用四种进程调度算法(轮转调度、静态优先级调度、动态优先级调度、最短进程优先调度)执行调度模拟。
(2)每个用来标识进程的进程表项(进程控制块 PCB)可用结构体来描述,包括以下字段(具体字段及数量可根据需要自行定义,此处仅供参考):
(a)进程标识数 ID。
(b) 进程优先数 PRIORITY,并规定优先数越大的进程,其优先权越高。
(c) 进程运行所需CPU总时间片数ALLTIME,已占用 CPU 时间片数 CPUTIME。当进程运行完毕时,ALLTIME 变为 0。
(d) 进程的待阻塞时间片数 STARTBLOCK,表示当进程再运行 STARTBLOCK个时间片后,进程将进入阻塞状态。
(e) 进程被阻塞的时间片数 BLOCKTIME ,表示已阻塞的进程再等待 BLOCKTIME 个时间片后,将转换成就绪状态。
(f) 进程状态 STATE。
(g) 队列指针 NEXT,用来将 PCB 排成队列。
(3)进程数量要求可以指定任意数量,每个进程运行所需的CPU时间数要求可以指定任意数量或随机生成。
(4)静态优先级调度,每个进程的优先级要求可以任意指定或随机生成。
(5)动态优先级调度原则:进程在就绪队列中呆一个时间片,优先数增加 1;进程每运行一个时间片,优先数减 3(这一规则主要用于动态优先级调度算法)。
(6)最短进程优先中的进程长度根据剩余所需CPU时间片数动态计算。
(7)为了观察每个进程的调度过程,程序应将每个时间片内的进程的情况显示出来,包括正在运行的进程,处于就绪队列中的进程和处于阻塞队列中的进程。
(8)要求在linux ubuntu环境下使用c/c++编写。
1.2.2部分调整
(1)本次模拟首先对四种调度方法分别进行了实现,因此各种调度算法内部的PCB数据结构存在着一定程度上的差别,但对于每种调度算法均采用了设计要求中规定的变量名程。
(2)后期对各种调度算法进行整合时,出现了变量命名之间的冲突,因此部分算法内部的变量命名出现了诸如RR(轮转调度)、DP(动态优先级)、SP(静态优先级)、SJF(最短进程优先)字样的前缀。
(3)在本次模拟中,提供了四种调度方法供用户选择,以此实现对N种进程采用4种不同的调度方法。
2 总体设计
2.1 总体结构
图2-1 模拟进程调度演示系统功能模块图
2.2 开发环境
Linux操作系统、VMware虚拟机、开发语言c/c++、HUAWEI MATEBOOK XPRO笔记本
3 算法设计
3.1轮转调度算法
在早期的时间片轮转法中,系统将所有的就绪进程按先来先服务的原则,排成一个队列,每次调度时,把CPU分配给队首进程,并令其执行一个时间片。如果就绪队列上存在N个进程,那么每个进程每次大约可获得1/N的处理机时间。
如图2-1功能模块图所示,在轮转调度方法种,需要对PCB块进行数据结构设计,并且完成对队列结点定义模块、队列初始化模块、进程队列创建模块、进程插入模块、进程输出模块、RR算法模块的实现。
具体流程如下:(虚线仅代表在程序编写时逻辑上的先后顺序,实现代表模块之间存在调用关系)
其中,RR轮转调度算法中设计的PCB数据结构如下:
3.2静态优先级调度算法
优先级调度算法中的静态优先级调度在一开始便根据各个进程的PRIORITY确定下来进程的顺序,优先级在整个运行期间保持不变。一般而言,确定进程优先级大小的依据主要有进程类型、进程对资源的需求、用户要求。静态优先级的调度方法简单易行,但不够精确,会出现进程长时间无法被调度的现象。
如图2-1功能模块图所示,在静态优先级调度算法种,除了对PCB数据块进行设计,还需要完成对进程队列创建模块、SP算法等模块的实现。
具体流程如下:
其中,SP静态优先级调度算法中设计的PCB数据结构如下:
3.3动态优先级调度算法
动态优先级调度算法是指在进程创建之初,赋予进程一个暂时的优先级别,随着进程的推进,进程的优先级别会随之改变,本次模拟中采用的规则为: 进程在就绪队列中呆一个时间片,优先数增加 1;进程每运行一个时间片,优先数减 3。这样的调度方法可以较为公平地实现进程间处理机的分配,避免了一个长期进程长期垄断处理机的现象。
如图2-1功能模块图所示,在动态优先级调度算法中,需对PCB数据块进行设计,此外还需完成对进程队列创建模块、DP算法等模块的实现。
具体流程如下:
其中,DP动态优先级调度算法中设计的PCB数据结构如下:
3.4最短进程优先调度算法
最短进程优先调度方法以进程的长短来计算优先级,本次模拟中采用进程所需的CPU时间片数来作为优先级的判定依据,即每个进程的剩余ALLTIME时间数。最短进程优先调度每次从队列中取出时间最短的进程运行。最短进程优先调度算法的缺点在于,必须预先知道进程运行所需时间、对ALLTIME较长的进程并不友好、当采用FCFS调度方法时,无法实现人机交互。此外,最短进程优先调度方法无法考虑到进程的紧急程度,因此无法保证紧急的作业得到及时处理。
如图2-1功能模块图所示,最短进程优先调度算法中,除对PCB数据块进行设计以外,还需实现进程队列创建模块、调度结果输出模块、SJF算法等模块。
具体流程如下:
依旧使用数组的形式来存放进程,便于实现依据次序标号对进程的直接查找以及调度 |
其中,SJF最短进程优先调度算法中设计的PCB数据结构如下:
4 系统实现
4.1 用户输入模块实现(部分主函数的实现)
#include"SJF.h"
#include"SP.h"
#include"RR.h"
#include"DP.h"
int main()
{
printf("【本次模拟除进程名以外的所有输入均为整数】\n\n\n");
int B;
printf("请选择PRIORITY、ALLTIME的生成方式:\n【1】手动输入\n【2】随机生成\n");
scanf("%d",&B);
int A;
printf("\n");
printf("请选择调度方法(输入对应序号即可)\n");
Q:printf("【1】轮转调度\n【2】最短进程优先调度\n【3】静态优先级调度\n【4】动态优先级调度\n");
scanf("%d",&A);
if (A>4)
{
printf("输入有误,请重新输入\n");
goto Q;
}
}
4.2 轮转调度模块实现
4.2.1 PCB数据结构设计
typedef struct pcb //定义进程控制块
{
char ID[MaxNum]; //进程号
int Arrive_Time; //进程到达时间,用以排序
int ALLTIME; //进程运行所需总时间
int WHLOLETIME; //固定运行时间
int FinishTime; //完成时间
double RUN_AROUND_TIME; //周转时间
double WeightWholeTime; //带权周转时间
char STATE; //进程状态
struct pcb *NEXT;
}RRPCB;
4.2.2队列结点定义模块
typedef struct //定义队列以及头结点尾结点
{
RRPCB *front,*rear;
}queue;
4.2.3队列初始化模块
queue *Init() //初始化队列
{
queue *HEAD;
HEAD=(queue*)malloc(sizeof(queue));
HEAD->front=NULL;
HEAD->rear=NULL;
return HEAD;
}
4.2.4进程队列创建模块
queue *CreatQueue(queue *head,int M,int B) //创建进程队列
{
char c[MaxNum];
char s='R';
int a,r,i;
if (B==1)
{
for(i=1;i<=M;i++)
{
printf("请输入第%d个进程的进程名:\n",i);
getchar();
cin.get(c,MaxNum);
printf("请输入第%d个进程的到达时间:\n",i);
scanf("%d",&a);
printf("请输入第%d个进程的服务时间:\n",i);
scanf("%d",&r);
head=Insert(head,c,a,r,s);
printf("\n");
}
}
else
{
for(i=1;i<=M;i++)
{
printf("请输入第%d个进程的进程名:\n",i);
getchar();
cin.get(c,MaxNum);
printf("请输入第%d个进程的到达时间:\n",i);
scanf("%d",&a);
r=(int)(rand()%12);//r即进程所需总时长
head=Insert(head,c,a,r,s);
printf("\n");
}
}
return head;
}
4.2.5进程插入模块
queue *Insert(queue *head,char c[MaxNum],int a,int r,char s) //将进程插入队列,每次取出队首的进程运行
{
RRPCB *p;
p=(RRPCB *)malloc(sizeof(RRPCB));
strcpy(p->ID,c);
p->Arrive_Time=a;
p->ALLTIME=r;
p->WHLOLETIME=r;
p->STATE=s;
p->NEXT=NULL;
if(Empty(head))
head->front=head->rear=p;
else
{
head->rear->NEXT=p;
head->rear=p;
}
return head;
}
4.2.6进程输出模块
void print(queue *head) //输出进程
{
RRPCB *p;
p=head->front;
if(!p)
printf("时间片轮转调度队列为空!\n");
while(p)
{
printf("ID=%s Arrvie_Time=%d ALLTIME=%d STATE=%c",p->ID,p->Arrive_Time,p->ALLTIME,p->STATE);
printf("\n");
p=p->NEXT;
}
}
4.2.7RR(轮转调度)算法模块
void RR(queue *head,int Time_Slice)
{
int t=head->front->Arrive_Time, lt=head->rear->Arrive_Time;
if(head->front->ALLTIME<Time_Slice)
t=t+head->front->ALLTIME;
else
t=t+Time_Slice;
//队列为空则无法调度
while(!Empty(head))
{
RRPCB *p1,*p2;
printf("\n时刻 进程 状态\n");
//当前运行的时间小于最后一个进程到达时间
while(t<lt)
{
p1=head->front;
printf("%2d %s",t,p1->ID);
p1->ALLTIME=p1->ALLTIME-Time_Slice;//判断在进程所需要的ALLTIME内是否可以完成,用ALLTIME-CPUTIME判断
//1.运行时间小于0,删除队首进程
if(p1->ALLTIME<=0)
{
p1->STATE='C';
printf(" %c\n",p1->STATE);
p1->FinishTime=t;
p1->RUN_AROUND_TIME=p1->FinishTime-p1->Arrive_Time;
p1->WeightWholeTime=p1->RUN_AROUND_TIME/p1->WHLOLETIME;
SumWT+=p1->RUN_AROUND_TIME;
SumWWT+=p1->WeightWholeTime;
printf("=========================================================\n");
printf("时刻%2d进程%s运行结束,进程%s周转时间=%5.2f,带权周转时间=%5.2f\n",t,p1->ID,p1->ID,p1->RUN_AROUND_TIME,p1->WeightWholeTime);
printf("=========================================================\n");
head->front=p1->NEXT;
free(p1);
}
//2.运行时间大于0,继续排队
else
{
printf(" %c\n",p1->STATE);
p2=p1->NEXT;
while(p2->NEXT && p2->Arrive_Time != t)
{
p2=p2->NEXT;
}
//没有新的进程到达时
//1.保持队首进程
//2.队首进程后移
if(p2->Arrive_Time != t)
{
RRPCB *p3=p1,*p4=NULL;
while(p3->NEXT && p3->Arrive_Time<t)
{
p4=p3;
p3=p3->NEXT;
}
if(p3->Arrive_Time>t)
{
if(p4!=p1) //p1插在p4后,头节点p1->NEXT
{
head->front=p1->NEXT;
p1->NEXT=p4->NEXT;
p4->NEXT=p1;
}
else
p4=p3=p2=NULL;
}
else
p4=p3=p2=NULL;
}
//新的进程到达
//队首进程插入在新进程之后,指针更新
else
{
head->front=p1->NEXT;
p1->NEXT=p2->NEXT;
p2->NEXT=p1;
}
}
//更新时间
if(head->front->ALLTIME<Time_Slice)
t=t+head->front->ALLTIME;
else
t=t+Time_Slice;
}
//ALLTIME大于最后一个进程到达的时间
while(t>=lt)
{
p1=head->front;
printf("%2d %s",t,p1->ID);
p1->ALLTIME=p1->ALLTIME-Time_Slice;
//1.运行时间小于0,删除队首进程
if(p1->ALLTIME<=0)
{
p1->STATE='C';
printf(" %c\n",p1->STATE);
p1->FinishTime=t;
p1->RUN_AROUND_TIME=p1->FinishTime-p1->Arrive_Time;
p1->WeightWholeTime=p1->RUN_AROUND_TIME/p1->WHLOLETIME;
SumWT+=p1->RUN_AROUND_TIME;
SumWWT+=p1->WeightWholeTime;
printf("=========================================================\n");
printf("时刻%2d进程%s运行结束,进程%s周转时间=%5.2f,带权周转时间=%5.2f\n",t,p1->ID,p1->ID,p1->RUN_AROUND_TIME,p1->WeightWholeTime);
printf("=========================================================\n");
//printf("时刻%2d进程%s运行结束",t,p1->pname);
head->front=p1->NEXT;
free(p1);
}
//2.运行时间大于0,进程插入队列末
else
{
printf(" %c\n",p1->STATE);
//队列中只有一个进程无需更改
if(!p1->NEXT)
head->front=p1;
//队列中的进程数大于1时
else
{
head->front=p1->NEXT;
head->rear->NEXT=p1;
head->rear=p1;
p1->NEXT=NULL;
}
}
//更新时间
if(Empty(head))
return;
else
{
if(head->front->ALLTIME<Time_Slice)
t=t+head->front->ALLTIME;
else
t=t+Time_Slice;
}
}
}
}
4.3 静态优先级调度模块实现
4.3.1PCB数据结构设计模块
struct PCB
{
char PNAME[20];
int PRIORITY;
int ALLTIME;
int CPUTIME;
char STATE;
struct PCB* NEXT;
int num;
};
4.3.2进程队列创建模块
struct PCB *processes, *Temp_Node;
//Temp_Node作为临时节点来创建链表
processes = Temp_Node = (struct PCB*)malloc(sizeof(struct PCB));
if (B==1)
{
for (int i = 1; i <= N; ++i)
{
struct PCB *p = (struct PCB*)malloc(sizeof(struct PCB));
printf("进程号No.%d:\n", i);
printf("输入进程名:");
scanf("%s", p->PNAME);
printf("输入进程优先数:");
scanf("%d", &p->PRIORITY);
printf("输入进程所需总时间:");
scanf("%d", &p->ALLTIME);
p->CPUTIME = 0;
p->STATE = 'W';
p->NEXT = NULL;
Temp_Node->NEXT = p;
Temp_Node = p;
p->num=p->ALLTIME;
printf("\n\n");
}
}
else
{
for (int i = 1; i <= N; ++i)
{
struct PCB *p = (struct PCB*)malloc(sizeof(struct PCB));
printf("进程号No.%d:\n", i);
printf("输入进程名:");
scanf("%s", p->PNAME);
p->PRIORITY=(int)(rand()%12);
p->ALLTIME=(int)(rand()%12);
p->num=p->ALLTIME;
p->CPUTIME = 0;
p->STATE = 'W';
p->NEXT = NULL;
Temp_Node->NEXT = p;
Temp_Node = p;
printf("\n\n");
}
}
4.3.3SP(静态优先级调度)算法模块
//processes作为头结点来存储链表
processes = processes->NEXT;
int Present_Time = 0;
struct PCB *P_INORDER = processes;
while (1)
{
++Present_Time;
Temp_Node = processes;
//对链表按照优先数排序
//P_INORDER用来存放排序后的链表
P_INORDER = SortList(P_INORDER);
printf("===============================================\n");
printf("当前时刻为: %d\n", Present_Time-1);
printf("===============================================\n");
printf("当前正在运行的进程是:%s\n", P_INORDER->PNAME);
P_INORDER->STATE = 'R';
P_INORDER->num--;
P_INORDER->CPUTIME++;
printf("PNAME STATE PRIORITY ALLTIME CPUTIME\n");
printf(" %s %c %d %d %d\n", P_INORDER->PNAME, P_INORDER->STATE, P_INORDER->PRIORITY, P_INORDER->num, P_INORDER->CPUTIME);
Temp_Node->STATE = 'W';
printf("当前就绪状态的队列为:\n\n");
//Temp_Node指向已经排序的队列
Temp_Node = P_INORDER->NEXT;
while (Temp_Node != NULL)
{
printf("PNAME STATE PRIORITY ALLTIME CPUTIME\n");
printf(" %s %c %d %d %d\n", Temp_Node->PNAME, Temp_Node->STATE, Temp_Node->PRIORITY, Temp_Node->ALLTIME, Temp_Node->CPUTIME);
Temp_Node = Temp_Node->NEXT;
}
//Temp_Node指向已经排序的链表
Temp_Node = P_INORDER;
struct PCB *PRE_TEMPNODE;
PRE_TEMPNODE = NULL; //PRE_TEMPNODE指向Temp_Node的前一个节点
while (Temp_Node != NULL)
{
if (Temp_Node->ALLTIME == Temp_Node->CPUTIME)
{
if (PRE_TEMPNODE == NULL)
{
Temp_Node = P_INORDER->NEXT;
P_INORDER = Temp_Node;
}
else
PRE_TEMPNODE->NEXT = Temp_Node->NEXT;
}
PRE_TEMPNODE = Temp_Node;
Temp_Node = Temp_Node->NEXT;
}
}
}
struct PCB* SortList(PCB* HL)
{
struct PCB* SL;
SL = (struct PCB*)malloc(sizeof(struct PCB));
SL = NULL;
struct PCB* r = HL;
while (r != NULL)
{
struct PCB* t = r->NEXT;
struct PCB* cp = SL;
struct PCB* PRE_TEMPNODE = NULL;
while (cp != NULL)
{
if (r->PRIORITY > cp->PRIORITY)
break;
else
{
PRE_TEMPNODE = cp;
cp = cp->NEXT;
}
}
if (PRE_TEMPNODE == NULL)
{
r->NEXT = SL;
SL = r;
}
else
{
r->NEXT = cp;
PRE_TEMPNODE->NEXT = r;
}
r = t;
}
return SL;
4.4 动态优先级调度模块实现
4.4.1PCB数据结构设计模块
typedef struct{
char ID;
int PRIORITY;
int CPUTIME;
int ALLTIME;
int STARTBLOCK;
int BLOCKTIME;
int STATE;//0-运行 1-阻塞 2-就绪 3-结束 4-未到达
int Arrive_Time;
int TIME;
}PROCESS;
4.4.2进程队列创建模块
IntDI=0,DPTime_Slice,max,l,l1,time1,flag=0,total=0,server[10],sum=0,DPN=0;
PROCESS pro[10];
cout<<"本程序中状态代表如下"<<endl<<"【0】-运行 【1】-阻塞 【2】-就绪 【3】-结束 【4】-未到达"<<endl<<endl;
if (B==1)
{
cout<<"请输入进程数:";
cin>>DPN;
cout<<"请设置时间片长度:";
cin>>DPTime_Slice;
cout<<"请输入各进程初始状态:"<<endl;
cout<<"ID PRIORITY Arrive_Time ALLTIME STARTBLOCK BLOCKTIME"<<endl;
for(DI=0;DI<DPN;DI++)
{//进程初始化
pro[DI].CPUTIME=0;
pro[DI].TIME=0;
cin>>pro[DI].ID>>pro[DI].PRIORITY>>pro[DI].Arrive_Time;
cin>>pro[DI].ALLTIME>>pro[DI].STARTBLOCK>>pro[DI].BLOCKTIME;
server[DI]=pro[DI].ALLTIME;
if(pro[DI].Arrive_Time==0) pro[DI].STATE=0;
else pro[DI].STATE=4;
}
}
else
{
cout<<"请输入进程数:";
cin>>DPN;
cout<<"请设置时间片长度:";
cin>>DPTime_Slice;
cout<<"请输入各进程初始状态:"<<endl;
cout<<"ID Arrive_Time STARTBLOCK BLOCKTIME"<<endl;
for (int DI = 0; DI < DPN; DI++)
{
pro[DI].CPUTIME=0;
pro[DI].TIME=0;
cin>>pro[DI].ID>>pro[DI].Arrive_Time;
cin>>pro[DI].STARTBLOCK>>pro[DI].BLOCKTIME;
pro[DI].PRIORITY=(int)(rand()%10);
pro[DI].ALLTIME=(int)(rand()%10);
server[DI]=pro[DI].ALLTIME;
if(pro[DI].Arrive_Time==0) pro[DI].STATE=0;
else pro[DI].STATE=4;
}
}
4.4.3DP(动态优先级调度)算法模块
do{
cout<<endl<<"当前时刻为:"<<total;
cout<<endl<<"========================各进程状态为======================"<<endl;
cout<<"ID PRIORITY CPUTIME ALLTIME STARTBLOCK BLOCKTIME STATE"<<endl;
for(DI=0;DI<DPN;DI++){
cout<<pro[DI].ID<<" "<<pro[DI].PRIORITY<<" "<<pro[DI].CPUTIME<<" ";
cout<<pro[DI].ALLTIME<<" "<<pro[DI].STARTBLOCK<<" "<<pro[DI].BLOCKTIME<<" "<<pro[DI].STATE;
cout<<endl;
}
total+=DPTime_Slice;
for(DI=0;DI<DPN;DI++){
if(pro[DI].STATE==4&&pro[DI].Arrive_Time<total){
pro[DI].STATE=1;
}
}
for(DI=0;DI<DPN;DI++){
time1=pro[DI].ALLTIME;
if(pro[DI].STATE==0){
if(pro[DI].ALLTIME<=DPTime_Slice){
pro[DI].ALLTIME=0;
pro[DI].STATE=3;
pro[DI].TIME=total-DPTime_Slice+time1;
}
else{
pro[DI].ALLTIME-=DPTime_Slice;
pro[DI].STARTBLOCK--;
if(pro[DI].STARTBLOCK==0){
pro[DI].STATE=1;
pro[DI].BLOCKTIME=time1;
pro[DI].STARTBLOCK=time1;
}
pro[DI].PRIORITY-=3;
pro[DI].TIME=total;
}
}
if(pro[DI].STATE==1){
pro[DI].BLOCKTIME--;
if(pro[DI].BLOCKTIME==0) pro[DI].STATE=2;
pro[DI].TIME=total;
}
if(pro[DI].STATE==2){
pro[DI].PRIORITY++;
pro[DI].TIME=total;
}
}
max=-100;
l1=-1;
l=-1;
for(DI=0;DI<DPN;DI++){
if(pro[DI].PRIORITY>max&&(pro[DI].STATE==0||pro[DI].STATE==2)){
l=DI;
max=pro[DI].PRIORITY;
}
if(pro[DI].STATE==0) l1=DI;
}
if(l!=-1&&l!=l1) pro[l].STATE=0;
if(l1!=-1) pro[l1].STATE=2;
flag=0;
for(DI=0;DI<DPN;DI++){
if(pro[DI].STATE!=3){
flag=1;
break;
}
}
if(flag==0) break;
}while(1);
cout<<endl<<"当前时刻:"<<total;
cout<<endl<<"========================各进程状态为======================"<<endl;
cout<<"ID PRIORITY CPUTIME ALLTIME STARTBLOCK BLOCKTIME STATE"<<endl;
for(DI=0;DI<DPN;DI++){
cout<<pro[DI].ID<<" "<<pro[DI].PRIORITY<<" "<<pro[DI].CPUTIME<<" ";
cout<<pro[DI].ALLTIME<<" "<<pro[DI].STARTBLOCK<<" "<<pro[DI].BLOCKTIME<<" "<<pro[DI].STATE;
cout<<endl;
}
cout<<endl<<"各进程运行结束!"<<endl;
cout<<"进程号 到达时间 结束时间 周转时间 带权周转时间"<<endl;
for(DI=0;DI<DPN;DI++){
cout<<" "<<pro[DI].ID<<" "<<pro[DI].Arrive_Time<<" "<<pro[DI].TIME<<" "<<pro[DI].TIME-pro[DI].Arrive_Time<<" "<<(float)(pro[DI].TIME-pro[DI].Arrive_Time)/server[DI]<<endl;
sum+=pro[DI].TIME-pro[DI].Arrive_Time;
}
cout<<"平均周转时间为:"<<(float)sum/DPN<<endl;
4.5 最短进程优先调度模块实现
4.5.1PCB数据结构设计模块
struct Process_struct{
int Number; //进程编号
char Name[MaxNum]; //进程名称
int ArrivalTime; //到达时间
int ServiceTime; //开始运行时间
int FinishTime; //运行结束时间
int SJF_ALLTIME; //运行时间
int STATE; //调度标志
int order; //运行次序
double WeightWholeTime; //周转时间
double AverageWT_SJF; //平均周转时间
double AverageWWT_SJF; //平均带权周转时间
}Process[MaxNum];
4.5.2进程队列创建模块
int PROCESSinput(int B) //进程参数输入
{
int i;
printf("请输入进程个数:\n");
scanf("%d",&SJFPN);
if (B==1)
{
for(i=0;i<SJFPN;i++)
{
printf("请输入第%d个进程名称:",i+1);
scanf("%s",Process[i].Name);
printf("请输入第%d个进程的到达时间:",i+1);
scanf("%d",&Process[i].ArrivalTime);
printf("请输入第%d个进程的ALLTIME:",i+1);
scanf("%d",&Process[i].SJF_ALLTIME);
Process[i].ServiceTime=0;
Process[i].FinishTime=0;
Process[i].WeightWholeTime=0;
Process[i].order=0;
Process[i].STATE=0;
printf("\n");
}
}
else
{
for(i=0;i<SJFPN;i++)
{
printf("请输入第%d个进程名称:",i+1);
scanf("%s",Process[i].Name);
printf("请输入第%d个进程的到达时间:",i+1);
scanf("%d",&Process[i].ArrivalTime);
Process[i].SJF_ALLTIME=(int)(rand()%11);
Process[i].ServiceTime=0;
Process[i].FinishTime=0;
Process[i].WeightWholeTime=0;
Process[i].order=0;
Process[i].STATE=0;
printf("\n");
}
}
return 0;
}
4.5.3调度结果输出模块
int OUTCOME() //调度结果输出
{
int i;
float turn_round_time=0,f1,w=0;
printf(" 进程名称 到达时间 运行时间 开始时间 结束时间 执行顺序 周转时间 带权周转时间\n");
for(i=0;i<SJFPN;i++)
{
Process[i].WeightWholeTime=Process[i].FinishTime-Process[i].ArrivalTime;
f1=Process[i].WeightWholeTime/Process[i].SJF_ALLTIME;
turn_round_time+=Process[i].WeightWholeTime;
w+=f1;
printf("时刻%d :",Process[i].ServiceTime,Process[i].Name);
printf(" %s %d %d %d %d %d %.2f %.2f\n",Process[i].Name,Process[i].ArrivalTime,Process[i].SJF_ALLTIME,Process[i].ServiceTime,Process[i].FinishTime,Process[i].order,Process[i].WeightWholeTime,f1);
}
printf("平均周转时间=%.2f\n",turn_round_time/SJFPN);
printf("带权平均周转时间=%.2f\n",w/SJFPN);
return 0;
}
4.5.4 SJF(最短进程优先调度)算法模块
int SJF(){ //短作业优先算法
int temp_time=0; //当期那时间
int i=0,j;
int PID_ORDERED,PRESENT_PNUMBER; //进程编号,当前已执行进程个数
float run_time;
run_time=Process[i].SJF_ALLTIME;
j=1;
while((j<SJFPN)&&(Process[i].ArrivalTime==Process[j].ArrivalTime)) //判断是否有两个进程同时到达
{
if(Process[j].SJF_ALLTIME<Process[i].SJF_ALLTIME)
{
run_time=Process[i].SJF_ALLTIME;
i=j;
}
j++;
}
//查找下一个被调度的进程
//对找到的下一个被调度的进程求相应的参数
PID_ORDERED=i;
Process[PID_ORDERED].ServiceTime=Process[PID_ORDERED].ArrivalTime;
Process[PID_ORDERED].FinishTime=Process[PID_ORDERED].ServiceTime+Process[PID_ORDERED].SJF_ALLTIME;
Process[PID_ORDERED].STATE=1;
temp_time=Process[PID_ORDERED].FinishTime;
Process[PID_ORDERED].order=1;
PRESENT_PNUMBER=1;
while(PRESENT_PNUMBER<SJFPN)
{
for(j=0;j<SJFPN;j++)
{
if((Process[j].ArrivalTime<=temp_time)&&(!Process[j].STATE))
{
run_time=Process[j].SJF_ALLTIME;
PID_ORDERED=j;
break;
}
}
for(j=0;j<SJFPN;j++)
{
if((Process[j].ArrivalTime<=temp_time)&&(!Process[j].STATE))
if(Process[j].SJF_ALLTIME<run_time)
{
run_time=Process[j].SJF_ALLTIME;
PID_ORDERED=j;
}
}
//查找下一个被调度的进程
//对找到的下一个被调度的进程求相应的参数
Process[PID_ORDERED].ServiceTime=temp_time;
Process[PID_ORDERED].FinishTime=Process[PID_ORDERED].ServiceTime+Process[PID_ORDERED].SJF_ALLTIME;
Process[PID_ORDERED].STATE=1;
temp_time=Process[PID_ORDERED].FinishTime;
PRESENT_PNUMBER++;
Process[PID_ORDERED].order=PRESENT_PNUMBER;
}return 0;
}
5 系统测试 (UTF-8编码 可在 WINDOWS &LINUX环境下运行)
5.1Linux环境下编译主程序生成a.out文件
5.2运行a.out文件 (运行时可选择PRIORITY以及ALLTIME的生成方式)
5.2.1轮转调度算法的实现演示
5.2.2静态优先级调度算法的实现演示
5.2.3动态优先级调度算法的实现演示
5.2.4最短进程优先调度算法的实现演示 (为体现各进程的作业时长选择手动输入)
6 设计小结
本次模拟,实现了进程的轮转调度、静态优先级调度、动态优先级调度、最短进程优先调度。在整个实现过程中,出现了许多问题,最值得注意的问题如下,:文章来源:https://www.toymoban.com/news/detail-480923.html
- 代码编写过程中的问题
- 四种调度算法中,动态优先级调度算法较为复杂,在实现进程的优先级更新时出现了较大的困难
- 在对静态优先级进行模拟时,由于对ALLTIME的使用限制,造成对ALLTIME的更新操作正常,最终通过添加num计数器,解决了ALLTIME在进程执行结束后归零的问题
- 由于各种调度方法的要求不一,因此对PCB结构的定义也出现了一定的选择问题
- 代码合并中的问题
- 对每种调度算法采用了不同的PCB结构,因此各PCB中的属性不一
- 每种调度算法中对某些属性的命名产生了冲突
- 在对程序进行合并时,最初使用了GOTO语句,但在考虑后,将程序更改为了SWITCH分支结构
- 程序运行中的问题
- 使用了部分Linux操作系统不支持的库函数,在Linux环境下运行时出现了部分编译错误。如gets()函数的使用,最终将其更改为了cin.get()函数。
- 在对库函数做修改后,Linux环境下运行程序时,四种调度均可正常实现,但对SP算法的调试并未彻底完成。当在Windows环境下使用原库函数时,程序可以正常无误地运行;在虚拟机中运行时,目前还未完成:由于库函数的使用导致“未知原因造成SP算法中,对4个及以上进程调度出现无限循环”的BUG。
本次模拟,到此并没有真正结束,对于程序的调试并没有真正达到我们满意的效果,但在Windows系统上已然完善,后续会继续对Linux操作系统下因为库函数的问题导致的程序细微异常进行处理,直至完善。文章来源地址https://www.toymoban.com/news/detail-480923.html
到了这里,关于操作系统课程设计进程调度模拟的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!