进程调度模拟算法

 

     

  

实验项目名称实验一  进程调度模拟算法

 

一、实验目的

进程调度是处理机管理的核心内容。本实验要求用高级语言编写模拟进程调度程序,以便加深理解有关进程控制快、进程队列等概念,并体会和了解优先数算法和时间片轮转算法的具体实施办法。

二、实验内容和要求

  1. 设计进程控制块PCB的结构,通常应包括:进程名、进程优先数(或轮转时间片数)、进程已占用的CPU时间、进程到完成还需要的时间、进程的状态、当前队列指针等。
  2. 编写两种调度算法程序:

1)      优先数调度算法程序;

2)      循环轮转调度算法程序。

  1. 将程序源代码和运行截图写入实验报告并提交。

三、实验步骤

  1. 实验准备

分别用两种调度算法对伍个进程进行调度。每个进程可有三种状态;执行状态(RUN)、 就绪状态(READY,包括等待状态)和完成状态(FINISH),并假定初始状态为就绪状态。

(一)进程控制块结构如下:

NAME——进程标示符

PRIO/ROUND——进程优先数/进程每次轮转的时间片数(设为常数 2) CPUTIME——进程累计占用 CPU 的时间片数

NEEDTIME——进程到完成还需要的时间片数

STATE——进程状态

NEXT——链指针

注:

1.为了便于处理,程序中进程的的运行时间以时间片为单位进行计算;

2.各进程的优先数或轮转时间片数,以及进程运行时间片数的初值,均由用户在程序运行时给定。

(二)进程的就绪态和等待态均为链表结构,共有四个指针如下:

RUN——当前运行进程指针

READY——就需队列头指针

TAIL—— 就需队列尾指针

FINISH—— 完成队列头指针

(三)程序说明

1.在优先数算法中,进程优先数的初值设为:

50-NEEDTIME

每执行一次,优先数减 1,CPU 时间片数加 1,进程还需要的时间片数减 1。 在轮转法中,采用固定时间片单位(两个时间片为一个单位),进程每轮转一次,CPU 时间片数加 2,进程还需要的时间片数减 2,并退出 CPU,排到就绪队列尾,等待下一次调度。

2.程序的模块结构提示如下: 整个程序可由主程序和如下 7 个过程组成:

(1)INSERT1——在优先数算法中,将尚未完成的 PCB 按优先数顺序插入到就绪队列中;

(2)INSERT2——在轮转法中,将执行了一个时间片单位(为 2),但尚未完成的进程 的 PCB,插到就绪队列的队尾;

(3)FIRSTIN——调度就绪队列的第一个进程投入运行;

(4)PRINT——显示每执行一次后所有进程的状态及有关信息。

(5)CREATE——创建新进程,并将它的 PCB 插入就绪队列;

(6)PRISCH——按优先数算法调度进程;

(7)ROUNDSCH——按时间片轮转法调度进程。

主程序定义 PCB 结构和其他有关变量。

  1. 上机调试
  2. 主要流程和源代码

 

源代码:

#include<iostream>

#include<string>

using namespace std;

typedef struct node

{

 char name[20]; //进程名

 int prio; //进程优先级

 int round; //分配CPU的时间片

 int cputime; //CPU执行时间

 int needtime; //进程执行所需时间

 char state; //进程状态

 int count; //记录执行次数

 struct node *next; //链表指针

}PCB;

int num;

//定义三个队列,就绪队列,执行队列,完成队列

PCB *ready = NULL; //就绪队列

PCB *run = NULL; //执行队列

PCB *finish = NULL; //完成队列

//取得第一个就绪节点

void GetFirst()

{

 run = ready;

 if (ready != NULL)

 {

   run->state = 'R';

   ready = ready->next;

   run->next = NULL;

 }

}

//优先级输出队列

void Output1()

{

 PCB *p;

 p = ready;

 while (p != NULL)

 {

   cout << p->name << "\t" << p->prio << "\t" << p->cputime << "\t" << p->needtime << "\t " << p->state << " \t " << p->count << endl;

   p = p->next;

 }

 p = finish;

 while (p != NULL)

 {

   cout << p->name << "\t" << p->prio << "\t" << p->cputime << "\t" << p->needtime << "\t " << p->state << " \t " << p->count << endl;

   p = p->next;

 }

 p = run;

 while (p != NULL)

 {

   cout << p->name << "\t" << p->prio << "\t" << p->cputime << "\t" << p->needtime << "\t " << p->state << " \t " << p->count << endl;

   p = p->next;

 }

}

//轮转法输出队列

void Output2()

{

 PCB *p;

 p = ready;

 while (p != NULL)

 {

   cout << p->name << "\t" << p->round << "\t" << p->cputime << "\t" << p->needtime << "\t " << p->state << "\t " << p->count << endl;

   p = p->next;

 }

 p = finish;

 while (p != NULL)

 {

   cout << p->name << "\t" << p->round << "\t" << p->cputime << "\t" << p->needtime << "\t " << p->state << "\t " << p->count << endl;

   p = p->next;

 }

 p = run;

 while (p != NULL)

 {

   cout << p->name << "\t" << p->round << "\t" << p->cputime << "\t" << p->needtime << "\t " << p->state << "\t " << p->count << endl;

   p = p->next;

 }

}

//创建优先级队列

//创建优先级队列,规定优先数越小,优先级越低

void InsertPrio(PCB *in)

{

 PCB *fst, *nxt;

 fst = nxt = ready;

 if (ready == NULL) //如果队列为空,则为第一个元素

 {

   in->next = ready;

   ready = in;

 }

 else //查到合适的位置进行插入

 {

   if (in->prio >= fst->prio) //比第一个还要大,则插入到队头

   {

     in->next = ready;

     ready = in;

   }

   else

   {

     while (fst->next != NULL) //移动指针查找第一个比它小的元素的位置进行插入

     {

       nxt = fst;

       fst = fst->next;

     }

     if (fst->next == NULL) //已经搜索到队尾,则其优先级数最小,将其插入到队尾即可

     {

       in->next = fst->next;

       fst->next = in;

     }

     else //插入到队列中

     {

       nxt = in;

       in->next = fst;

     }

   }

 }

}

//将进程插入到就绪队列尾部

void InsertTime(PCB *in)

{

 PCB *fst;

 fst = ready;

 if (ready == NULL)

 {

   in->next = ready;

   ready = in;

 }

 else

 {

   while (fst->next != NULL)

   {

     fst = fst->next;

   }

   in->next = fst->next;

   fst->next = in;

 }

}

//将进程插入到完成队列尾部

void InsertFinish(PCB *in)

{

 PCB *fst;

 fst = finish;

 if (finish == NULL)

 {

   in->next = finish;

   finish = in;

 }

 else

 {

   while (fst->next != NULL)

   {

     fst = fst->next;

   }

   in->next = fst->next;

   fst->next = in;

 }

}

//优先级调度输入函数

void PrioCreate()

{

 PCB *tmp;

 int i;

 cout << "Enter the name and needtime:" << endl;

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

 {

   if ((tmp = (PCB *)malloc(sizeof(PCB))) == NULL)

   {

     cerr << "malloc" << endl;

     exit(1);

   }

   cin >> tmp->name;

   getchar();

   cin >> tmp->needtime;

   tmp->cputime = 0;

   tmp->state = 'W';

   tmp->prio = 50 - tmp->needtime; //设置其优先级,需要的时间越多,优先级越低

   tmp->round = 0;

   tmp->count = 0;

   InsertPrio(tmp); //按照优先级从高到低,插入到就绪队列

 }

 cout << "进程名\t优先级\tcpu时间\t需要时间 进程状态 计数器" << endl;

}

//时间片输入函数

void TimeCreate()

{

 PCB *tmp;

 int i;

 cout << "输入进程名字和进程时间片所需时间:" << endl;

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

 {

   if ((tmp = (PCB *)malloc(sizeof(PCB))) == NULL)

   {

     cerr << "malloc" << endl;

     exit(1);

   }

   cin >> tmp->name;

   getchar();

   cin >> tmp->needtime;

   tmp->cputime = 0;

   tmp->state = 'W';

   tmp->prio = 0;

   tmp->round = 2;

   tmp->count = 0;

   InsertTime(tmp);

 }

 cout << "进程名\t轮数\tCPU时间\t需要时间 进程状态 计数器" << endl;

}

//按照优先级调度,每次执行一个时间片

void Priority()

{

 int flag = 1;

 GetFirst();

 while (run != NULL)

 {

   Output1();

   while (flag)

   {

     run->prio -= 3; //优先级减去三

     run->cputime++; //CPU时间片加一

     run->needtime--;//进程执行完成的剩余时间减一

     if (run->needtime == 0)//如果进程执行完毕,将进程状态置为F,将其插入到完成队列

     {

       run->state = 'F';

       run->count++;

       InsertFinish(run);

       flag = 0;

     }

     else //将进程状态置为W,入就绪队列

     {

       run->state = 'W';

       run->count++; //进程执行的次数加一

       InsertTime(run);

       flag = 0;

     }

   }

   flag = 1;

   GetFirst(); //继续取就绪队列队头进程进入执行队列

 }

}

void RoundRun() //时间片轮转调度算法

{

 int flag = 1;

 GetFirst();

 while (run != NULL)

 {

   Output2();

   while (flag)

   {

     run->count++;

     run->cputime++;

     run->needtime--;

     if (run->needtime == 0) //进程执行完毕

     {

       run->state = 'F';

       InsertFinish(run);

       flag = 0;

     }

     else if (run->count == run->round)//时间片用完

     {

       run->state = 'W';

       run->count = 0; //计数器清零,为下次做准备

       InsertTime(run);

       flag = 0;

     }

   }

   flag = 1;

   GetFirst();

 }

}

int main(void)

{

 int n;

 cout << "输入进程个数:" << endl;

 cin >> num;

 getchar();

 cout << "-----------------进程调度算法模拟----------------------" << endl;

 cout << " 1、优先级调度算法" << endl;

 cout << " 2、循环轮转调度算法 " << endl;

 cout << "-------------------------------------------------------" << endl;

 cout << "输入选择序号:" << endl;

 cin >> n;

 switch (n)

 {

 case 1:

   cout << "优先级调度:" << endl;

   PrioCreate();

   Priority();

   Output1();

   break;

 case 2:

   cout << "循环轮转算法:" << endl;

   TimeCreate();

   RoundRun();

   Output2();

   break;

 case 0:

   exit(1);

   break;

 default:

   cout << "Enter error!" << endl;

   break;

 }

 cout << endl;

 return 0;

}

  1. 遇到的主要问题和解决方法

问题:队列是先进先出的 , 在优先级算法中怎么来向链表中插入新的进程 , 使其能够按优先级排序 。

解决方法: 第一想到的是用数组,后来发现不如链表方便,所以换成链表。

四、实验结果

程序开始运行后,首先提示:请用户选择算法,输入进程名和相应的 NEEDTIME 值。

每次显示结果均为如下 5 个字段:

name cputime needtime priority state

注:

1.在 state 字段中,"R"代表执行态,"W"代表就绪(等待)态,"F"代表完成态。

2.应先显示"R"态的,再显示"W"态的,再显示"F"态的。

3.在"W"态中,以优先数高低或轮转顺序排队;在"F"态中,以完成先后顺序排队。

 

 

五、实验总结

通过这次实验,我学习了进程调度模拟算法,对进程调度有了更深一层次的理解,同时也提高了自己的编程能力,感觉自己受益匪浅。

posted @ 2022-04-12 01:17  潘福龙  阅读(245)  评论(0编辑  收藏  举报