操作系统——使用动态优先权的进程调度算法的模拟

来源:互联网 发布:知乎周刊怎么看 编辑:程序博客网 时间:2024/06/05 19:12

实验目的:通过动态优先权算法的模拟加深进程概念和进程调度过程的理解,并学习撰写规范的科学研究报告。

设计思路:

1.对N个进程采用动态优先权算法的进程调度;

2.每个用来标识进程的进程控制块PCB用结构描述,包括以下字段:进程标识数ID,进程优先数PRIORITY,进程以占用的CPU时间CPUTIME,进程还需占用的CPU时间ALLTIME,进程状态STATE等。

3.优先数改变的原则:进程在就绪队列中呆一个时间片,优先数增加1,进程每运行一个时间片优先数减3。

4.设置调度前的初始状态。

5.将每个时间片内的进程情况显示出来。

(二)涉及的内容或知识点

本实验涉及到动态优先权算法,进程调度过程等知识点。

(三)采用的方法和手段

学生查阅资料,设计方案,编写源程序,上机调试,测试,结果分析。在规定的时间内,由学生独立完成实验过程,并对结果进行科学分析,撰写出规范的实验报告。

(四)考察点

对等动态优先权算法,进程调度过程掌握情况;考查学生的写算法和编程能力等;考查学生的分析问题和解决问题的能力;实验报告的撰写能力等。

设计思路:

(1)先对就绪队列,阻塞队列,cpu的进行初始化。

(2)进行进程调度的选择。

       1)cpu,就绪队列和阻塞队列中的进程数不为0。判断cpu是否空闲。

              a.cpu空闲的话,从就绪队列中选取优先级最大的;而如果就绪队列为空,则从阻塞队列中选取第一个进程。选中的进程的cputime设置为0。

              b.cpu上有进程,则更新cpu上进程的状态,打印cpu上进程的id。如果cpu上的进程的alltime已经为0,即进程已经完成了,更新该进程的状态为finish,将cpu清空。如果进程在cpu上的时间达到starttime,将其放到阻塞队列,清空cpu。

       2)更新阻塞队列和就绪队列中的进程中的状态,打印就绪队列和阻塞队列的进程的id。

       3)打印每个进程的状态。

(3)重复上面的步骤,直到没有cpu,就绪队列,阻塞队列中都没有进程了。

 

在实现的程序实现过程中就绪队列和阻塞队列都设置为双向指针,方便查找,取出,插入进程。

就绪队列在插入时,是根据优先级的大小插入到队列中,并且由于每一个时间片后,进程在就绪队列中等待,优先级数值增加相同,所以保证了就绪队列的优先级由头指针开始呈递减状态。因此每次从就绪队列取出优先级最大的进程放到cpu上,都能直接取就绪队列的第一个进程。

阻塞队列在插入时,是根据blocktime的时间的大小来插入到队列中,blocktime的大小是不能发生改变的,所以设置了另外一个变量waittime,记录了进程在阻塞队列中等待的时间。每等待一个时间片,waittime+1,当等待时间到(即waittime > blocktime)的时候,则将该进程插入到就绪队列中。

每个时间片运行后,在更新进程状态时,都将其现在的状态记录到rec中。

 

下面先对本程序中涉及的函数进行简单解释(除了main()函数在程序的最后,其他函数按照出现的先后顺序介绍)。

主函数——main():初始化cpu,就绪队列和阻塞队列。主要工作进行进程的调度,每一个时间片后,调用函数进行cpu,就绪队列,阻塞队列中进程的状态更新,该时间片后,对每个进程状态进行打印。

 

就绪队列的函数分析——ready_push(),ready_pop(),ready_updata(),ready_work()四个函数。

分析:

ready_push()函数,作用:将新的进程按照优先级大小插入就绪队列,保证队列按优先级大小呈递减状态。

ready_pop()函数,作用:将就绪队列中优先级最大的进程弹出队列,由于就绪队列中是按优先级大小排列的,所以也是弹出第一个就绪进程。

ready_updata()函数,作用:每个时间片后,更新就绪队列中进程的优先级。每过一个时间片段后,就绪队列中每个进程的优先级+1。

ready_work()函数,作用:按照优先级打印就绪队列中的进程id,如果就绪队列中没有进程那就打印为NULL。并且记录经过一个时间片后就绪队列中每个进程的状态RECORD[pro->id]。

 

阻塞队列的函数分析——block_push(),block_pop(),block_updata(),block_work()四个函数。

block_push()函数,作用:将新的进程按照blocktime的大小插入阻塞队列中,保证队列按阻塞时间大小呈递增的状态。

block_pop()函数,作用:取出阻塞队列的第一个进程。

block_updata()函数,作用:每个时间片后,更新阻塞队列中进程的等待时间,每过一个时间片,阻塞队列中每个进程的等待时间加一。如果进程的阻塞时间等于等待时间,那么将该进程放到就绪队列中。

block_work()函数,作用:打印阻塞队列中进程的id,如果阻塞队列中没有进程那就打印NULL,并且记录经过一个时间片后,就绪队列中每个进程的状态。

 

关于cpu的函数分析——cpu_work()

cpu_work()函数,作用打印cpu上进程的id,更新cpu上进程的状态,priority-3; alltime-1;cputime+1;并且记录经过一个时间片后,cpu上进程的状态。

 

init()函数,作用:根据给的原始数据对cpu,就绪队列,阻塞队列进行初始化。

print_table()函数,作用:每个时间片后,按照规格打印出每个进程的状态。

 

由于代码是使用纯c语言实现的,而且构造了双向链表故代码长了点。

源代码:

#include <stdio.h>

#include <stdlib.h>

 

#define N 5

 

enum State{Ready,Run,Block,Finish};

 

struct PCB //数据结构

{

       intid;

       intpriority;

       intcputime;

       intalltime;

       intstartblock;//在cpu中能运行的时间

       intblocktime;//阻塞了多久后,进入就绪队列

       intwaittime;//*在阻塞队列中等待的时间

       Statestate;

       PCB*next;

       PCB*pre;

}*ready_pro,*block_pro,*ready_tail,*block_tail;//就绪,阻塞队列,记录其头指针,

int ready_num,block_num;//就绪,运行,阻塞队列中进程的数量。

PCB record[N];

 

//原始数据

int id[] = {0,1,2,3,4};

int priority[] = {9,38,30,29,0};

int cputime[] = {0,0,0,0,0};

int alltime[] = {3,3,6,3,4};

int startblock[] = {2,-1,-1,-1,-1};

int blocktime[] = {3,0,0,0,0};

State state[] ={Ready,Ready,Ready,Ready,Ready};

 

//将新的进程插入到就绪队列中

//用插入排序的方法,保证了就绪队列的值是按照大小排序的,

void ready_push(PCB* pro)

{

       pro->state= Ready;

       if(!ready_num)//如果是就绪队列为空,则放在头指针的位置,尾指针也赋值为pro

       {

              ready_pro= pro;

              ready_tail= pro;

       }

       else

       {

              PCB*this_pro = ready_pro;

              while(this_pro!= NULL)//插入的进程和就绪队列中的进程进行比较,插入到合适的位置

              {

                     if(this_pro->priority> pro->priority)//如果当前进程的优先级高则和下一个进程比较

                            this_pro= this_pro->next;

                     else//如果当前进程的优先级比pro低,则插在当前进程前面

                     {

                            if(this_pro== ready_pro)//如果是头指针则要改ready_pro的值

                            {

                                   pro->next= this_pro;

                                   this_pro->pre= pro;

                                   ready_pro= pro;

                            }

                            else//如果不是头指针则,插入队列中

                            {

                                   pro->next= this_pro;

                                   pro->pre= this_pro->pre;

                                   this_pro->pre->next= pro;

                                   this_pro->pre= pro;

                                  

                            }

                            break;//插入后退出循环

                     }

              }

              if(this_pro== NULL)//如果pro的优先级最小则插到队伍的最后

              {

                     ready_tail->next= pro;

                     pro->pre= ready_tail;

                     ready_tail= pro;//把ready_tail赋值为pro;

              }

       }

       ready_num++;

}

PCB* ready_pop()//就绪进程出队,将优先级最高的进程pop出去

{

       PCB*max_pro;

       //优先级最高的进程就是第一个进程

       max_pro=  ready_pro;

       ready_pro= ready_pro->next;

 

       if(ready_pro== NULL)//如果就绪队列出队后为空,则尾指针也需要赋值为NULL

              ready_tail= NULL;

       else//否则就绪队列头指针的前驱为空

       {

              ready_pro->pre= NULL;

              max_pro->next= NULL;

       }

       ready_num--;

       returnmax_pro;

}

 

void ready_updata()//每个时刻就绪队列中进程优先级的更新

{

       PCB*pro = ready_pro;

       while(pro!= NULL)

       {

              pro->priority++;

              pro= pro->next;

       }

}

void ready_work()

{

       printf("READY_QUEUE:");

       PCB*pro = ready_pro;

       if(pro== NULL)

              printf("NULL");

       while(pro!= NULL)

       {

              printf("->%d",pro->id);

              record[pro->id].id= pro->id;

              record[pro->id].priority= pro->priority;

              record[pro->id].cputime= pro->cputime;

              record[pro->id].alltime= pro->alltime;

              record[pro->id].startblock= pro->startblock;

              record[pro->id].blocktime= pro->blocktime;

              record[pro->id].state= pro->state;

              pro= pro->next;

       }

       printf("\n");

}

 

void block_push(PCB* pro)//进入阻塞队列

{

       block_num++;

       pro->state= Block;

       if(block_pro== NULL)//如果是阻塞队列空,则加入放在第一位

       {

              pro->next= NULL;

              pro->pre= NULL;

              block_pro= pro;

              block_tail= pro;

       }

       else//如果非空,插入排序,则按照所需要的时间长短放在阻塞队列中,时间越短越靠前,

       {

              PCB*this_pro = block_pro;

              while(this_pro!= NULL)

              {

                     if(this_pro->blocktime< pro->blocktime)//如果当前进程的阻塞时间小于pro则pro与下一个比较

                            this_pro= this_pro->next;

                     else

                     {

                            if(this_pro== block_pro)//如果是头指针则要改block_pro的值

                            {

                                   pro->next= this_pro;

                                   pro->pre= NULL;

                                   this_pro->pre= pro;

                                   block_pro= pro;

                            }

                            else//如果不是头指针则,插入队列中

                            {

                                   pro->next= this_pro;

                                   pro->pre= this_pro->pre;

                                   this_pro->pre->next= pro;

                                   this_pro->pre= pro;

                            }

                            break;//插入后退出循环

                     }

                     if(this_pro== NULL)//如果在最后则修改尾指针

                     {

                            block_tail->next= pro;

                            pro->pre= block_tail;

                            block_tail= pro;

                     }

              }

       }

}

PCB* block_pop()//取阻塞队列的队首

{

       PCB*pro;

       pro= block_pro;

       block_num--;

       if(!block_num)//只有一个值

       {

              block_pro= NULL;

              block_tail= NULL;

       }

       else//不止一个值

       {

              block_pro= block_pro->next;

              block_pro->pre= NULL;

       }

       pro->next= NULL;

       returnpro;

}

 

void block_updata()

{

       PCB*pro = block_pro;

       while(pro!= NULL)

       {

              pro->waittime++;

              //如果等待时间大于阻塞时间,则将进程放到就绪队列中

              if(pro->waittime> pro->blocktime)//如果等待时间大于阻塞时间,则将进程放到就绪队列中

              {

                     PCB*process = pro;

                     process->priority--;//先运行阻塞队列,需要减去1,在就绪队列中加回

                     if(process== block_pro)//如果是在队首

                     {

                            process= block_pop();//取出队首元素

                            pro= block_pro;//下一个需要判断的pro就等于队首元素

                     }

                     elseif(process == block_tail)//如果在队尾

                     {

                            block_tail= block_tail->pre;

                            process->pre= NULL;

                            process->waittime= 0;

                            pro= NULL;

                     }

                     else//如果在队伍中间

                     {

                            pro->pre->next= pro->next;

                            pro->next->pre= pro->pre;

                            pro= pro->next;

                            process->pre= NULL;

                            process->next= NULL;

                            process->waittime= 0;

                     }

                     ready_push(process);

              }

              else

                     pro= pro->next;

       }

}

void block_work()//打印阻塞队列的信息

{

       printf("BLOCK_QUEUE:");

       PCB*pro = block_pro;

       if(pro== NULL)

              printf("NULL");

       while(pro!= NULL)

       {

              printf("->%d",pro->id);

              record[pro->id].id= pro->id;

              record[pro->id].priority= pro->priority;

              record[pro->id].cputime= pro->cputime;

              record[pro->id].alltime= pro->alltime;

              record[pro->id].startblock= pro->startblock;

              record[pro->id].blocktime= pro->blocktime;

              record[pro->id].state= pro->state;

              pro= pro->next;

       }

       printf("\n");

}

void cpu_work(PCB *cpu_pro)

{

       if(cpu_pro== NULL)

       {

              printf("RUNNINGPROG:NULL\n");

              return;

       }

       if(!cpu_pro->alltime)

              return;

       cpu_pro->priority-= 3;

       cpu_pro->alltime--;

       cpu_pro->cputime++;

       printf("RUNNINGPROG:%d\n",cpu_pro->id);

       record[cpu_pro->id].id= cpu_pro->id;

       record[cpu_pro->id].priority= cpu_pro->priority;

       record[cpu_pro->id].cputime= cpu_pro->cputime;

       record[cpu_pro->id].alltime= cpu_pro->alltime;

       record[cpu_pro->id].startblock= cpu_pro->startblock;

       record[cpu_pro->id].blocktime= cpu_pro->blocktime;

       record[cpu_pro->id].state= cpu_pro->state;

}

 

 

void init()//初始化

{

       //初始化就绪队列,运行队列和阻塞队列

       block_pro= NULL;

       block_tail= NULL;

       block_num= 0;

 

       ready_num= 0;

       ready_pro= NULL;

       ready_tail= NULL;

 

       inti;

       PCB*pro;

       for(i= 0;i < N;i++)

       {

              pro= (PCB*)malloc(sizeof(PCB));

              pro->id= id[i];

              pro->priority= priority[i];

              pro->cputime= cputime[i];

              pro->alltime= alltime[i];

              pro->startblock= startblock[i];

              pro->blocktime= blocktime[i];

              pro->waittime = 0;

              pro->pre= NULL;

              pro->next= NULL;

              ready_push(pro);

       }

}

 

void print_table()

{

       inti;

       printf("===========================================================\n");

       printf("ID        \t%d    \t%d     \t%d     \t%d   \t%d \n",

              record[0].id,record[1].id,record[2].id,record[3].id,record[4].id);

       printf("PRIORITY  \t%d    \t%d     \t%d     \t%d   \t%d \n",

              record[0].priority,record[1].priority,record[2].priority,record[3].priority,record[4].priority);

       printf("CPUTIME   \t%d    \t%d     \t%d    \t%d    \t%d \n",

              record[0].cputime,record[1].cputime,record[2].cputime,record[3].cputime,record[4].cputime);

       printf("ALLTIME   \t%d    \t%d     \t%d     \t%d   \t%d \n",

              record[0].alltime,record[1].alltime,record[2].alltime,record[3].alltime,record[4].alltime);

       printf("STARTBLOCK\t%d     \t%d    \t%d     \t%d    \t%d \n",

              record[0].startblock,record[1].startblock,record[2].startblock,record[3].startblock,record[4].startblock);

       printf("BLOCKTIME\t%d     \t%d     \t%d    \t%d    \t%d \n",

              record[0].blocktime,record[1].blocktime,record[2].blocktime,record[3].blocktime,record[4].blocktime);

       printf("STATE     \t");

       for(i= 0;i < N;i++)

       {

              if(record[i].state== Run)

                     printf("RUN    \t");

              elseif(record[i].state == Ready)

                     printf("READY  \t");

              elseif(record[i].state == Finish)

                     printf("FINISH\t");

              elseif(record[i].state == Block)

                     printf("BLOCK  \t");

       }

       printf("\n");

}

int main()

{

       init();//初始化;

 

       PCB*cpu_pro = NULL;

       intcpu_num = 0;

       inttimes = 0;

       inti = 0;

 

       printf("第%d个时间片后:\n",times);

       cpu_work(cpu_pro);

       ready_work();

       block_work();

       print_table();

 

 

       while(1)

       {

              //如果三个队列中都没有进程则推出调用

              if(!ready_num&&!block_num&&!cpu_num)

                     break;

      

              if(!cpu_num)//如果cpu空闲则调用一个就绪队列中的进程

              {

                     if(ready_num> 0)//如果就绪队列非空,则调出优先级最高的进程

                     {

                            cpu_pro= ready_pop();

                     }

                     else//如果就绪队列为空,则调出阻塞队列的第一个值

                     {

                            cpu_pro= block_pop();

                     }

                     cpu_num= 1;

                     cpu_pro->state= Run;

                     cpu_pro->cputime= 0;//开始运行的时间为0;

              }

              times++;

              printf("\n第%d个时间片后:\n",times);

              cpu_work(cpu_pro);

             

              //如果alltime == 0,进程结束,释放内存

              if(!cpu_pro->alltime)

              {

                     cpu_pro->state= Finish;

                     record[cpu_pro->id].id= cpu_pro->id;

                     record[cpu_pro->id].priority= cpu_pro->priority;

                     record[cpu_pro->id].cputime= cpu_pro->cputime;

                     record[cpu_pro->id].alltime= cpu_pro->alltime;

                     record[cpu_pro->id].startblock= cpu_pro->startblock;

                     record[cpu_pro->id].blocktime= cpu_pro->blocktime;

                     record[cpu_pro->id].state= cpu_pro->state;

                     free(cpu_pro);

                     cpu_num= 0;

              }

              //更新阻塞和就绪队列中的信息

              block_updata();

              ready_updata();

 

              //显示就绪、阻塞队列的信息

              ready_work();

              block_work();

 

              print_table();

 

              //如果在cpu上运行时间达到了startblock并且alltime还不为0,则放到阻塞队列中,

              if(cpu_pro->cputime== cpu_pro->startblock&&cpu_pro->alltime > 0)

              {

                     //在放入阻塞队列中;

                     cpu_pro->cputime= 0;

                     cpu_pro->waittime= 0;

                     block_push(cpu_pro);

                     cpu_num= 0;

              }

       }

       printf("\n模拟进程调度算法结束!\n");

       return0;

}



0 0
原创粉丝点击