实验三 进程调度模拟程序

 13物联网        201306104134           郑伯瑜一

1. 目的和要求
实验目的

用高级语言完成一个进程调度程序,以加深对进程的概念及进程调度算法的理解。

实验要求

设计一个有 N(N不小于5)个进程并发执行的进程调度模拟程序。

进程调度算法:“时间片轮转法”调度算法对N个进程进行调度。

 

2. 实验内容
完成两个算法(简单时间片轮转法、多级反馈队列调度算法)的设计、编码和调试工作,完成实验报告。

 

1) 每个进程有一个进程控制块(PCB)表示。进程控制块包含如下信息:进程名、优先级、到达时间、需要运行时间、已用CPU时间、进程状态等等。

2) 每个进程的状态可以是就绪 r(ready)、运行R(Running)、或完成F(Finished)三种状态之一。

3) 就绪进程获得 CPU后都只能运行一个时间片。用已占用CPU时间加1来表示。

4) 如果运行一个时间片后,进程的已占用 CPU时间已达到所需要的运行时间,则撤消该进程,如果运行一个时间片后进程的已占用CPU时间还未达所需要的运行时间,也就是进程还需要继续运行,应把它插入就绪队列等待下一次调度。

5) 每进行一次调度,程序都打印一次运行进程、就绪队列中各个进程的 PCB,以便进行检查。   

6) 重复以上过程,直到所要进程都完成为止。

 

3. 实验原理及核心算法
“轮转法”有简单轮转法、多级反馈队列调度算法。

(1). 简单轮转法的基本思想是:

所有就绪进程按 FCFS排成一个队列,总是把处理机分配给队首的进程,各进程占用CPU的时间片长度相同。如果运行进程用完它的时间片后还未完成,就把它送回到就绪队列的末尾,把处理机重新分配给队首的进程。直至所有的进程运行完毕。

 

(2). 多级反馈队列调度算法的基本思想是:

将就绪队列分为N级(N=3~5),每个就绪队列优先数不同并且分配给不同的时间片:队列级别越高,优先数越低,时间片越长;级别越小,优先数越高,时间片越短。

系统从第一级调度,当第一级为空时,系统转向第二级队列,.....当处于运行态的进程用完一个时间片,若未完成则放弃CPU,进入下一级队列。

当进程第一次就绪时,进入第一级队列。

 

4. 实验环境
自主选择实验环境。可以选用Turbo C作为开发环境。也可以选用Windows下的可视化环境,利用各种控件较为方便。

 

5.源代码

  1 #include <stdio.h>
  2 #include <stdlib.h>
  3 #include <string.h>
  4 typedef struct node
  5 {
  6    char name[10];  /*进程标识符*/
  7    int prio;   /*进程优先数*/
  8    int round;  /*进程时间轮转时间片*/
  9    int cputime; /*进程占用CPU时间*/
 10    int needtime; /*进程到完成还要的时间*/
 11    int count;  /*计数器*/
 12    char state; /*进程的状态*/
 13    struct node *next; /*链指针*/
 14 }PCB;
 15 PCB *finish,*ready,*tail,*run; /*队列指针*/
 16 int N; /*进程数*/
 17 /*将就绪队列中的第一个进程投入运行*/
 18 firstin()
 19 {
 20    run=ready;   /*就绪队列头指针赋值给运行头指针*/
 21    run->state='R';   /*进程状态变为运行态*/
 22    ready=ready->next;  /*就绪对列头指针后移到下一进程*/
 23 }
 24 void prt1(char a)
 25 {
 26    if(toupper(a)=='P') /*优先数法*/
 27       printf("  name     cputime  needtime  priority  state\n");
 28    else
 29       printf("  name     cputime  needtime   count   round     state\n");
 30 }
 31 /*进程PCB输出*/
 32 void prt2(char a,PCB *q)
 33 {
 34    if(toupper(a)=='P')  /*优先数法的输出*/
 35       printf("  %-10s%-10d%-10d%-10d %c\n",q->name,
 36        q->cputime,q->needtime,q->prio,q->state);
 37    else/*轮转法的输出*/
 38       printf("  %-10s%-10d%-10d%-10d%-10d %-c\n",q->name,
 39        q->cputime,q->needtime,q->count,q->round,q->state);
 40 }
 41 /*输出函数*/
 42 void prt(char algo)
 43 {
 44    PCB *p;
 45    prt1(algo);  /*输出标题*/
 46    if(run!=NULL) /*如果运行指针不空*/
 47       prt2(algo,run); /*输出当前正在运行的PCB*/
 48    p=ready;  /*输出就绪队列PCB*/
 49    while(p!=NULL)
 50    {
 51       prt2(algo,p);
 52       p=p->next;
 53    }
 54    p=finish;  /*输出完成队列的PCB*/
 55    while(p!=NULL)
 56    {
 57       prt2(algo,p);
 58       p=p->next;
 59    }
 60    getchar();  /*压任意键继续*/
 61 }
 62 /*优先数的插入算法*/
 63 insert1(PCB *q)
 64 {
 65    PCB *p1,*s,*r;
 66    int b;
 67    s=q;  /*待插入的PCB指针*/
 68    p1=ready; /*就绪队列头指针*/
 69    r=p1; /*r做p1的前驱指针*/
 70    b=1;
 71    while((p1!=NULL)&&b)  /*根据优先数确定插入位置*/
 72       if(p1->prio>=s->prio)
 73       {
 74   r=p1;
 75      p1=p1->next;
 76       }
 77       else
 78      b=0;
 79    if(r!=p1)  /*如果条件成立说明插入在r与p1之间*/
 80    {
 81       r->next=s;
 82       s->next=p1;
 83    }
 84    else
 85    {
 86       s->next=p1;  /*否则插入在就绪队列的头*/
 87       ready=s;
 88    }
 89 }
 90 /*轮转法插入函数*/
 91 insert2(PCB *p2)
 92 {
 93    tail->next=p2;  /*将新的PCB插入在当前就绪队列的尾*/
 94    tail=p2;
 95    p2->next=NULL;
 96 }
 97 /*优先数创建初始PCB信息*/
 98 void create1(char alg)
 99 {
100    PCB *p;
101    int i,time;
102    char na[10];
103    ready=NULL; /*就绪队列头指针*/
104    finish=NULL;  /*完成队列头指针*/
105    run=NULL; /*运行队列指针*/
106    printf("输入进程名称和运行时间\n"); /*输入进程标识和所需时间创建PCB*/
107    for(i=1;i<=N;i++ )
108    {
109       p=malloc(sizeof(PCB));
110       scanf("%s",na);
111       scanf("%d",&time);
112       strcpy(p->name,na);
113       p->cputime=0;
114       p->needtime=time;
115       p->state='w';
116       p->prio=50-time;
117       if(ready!=NULL) /*就绪队列不空调用插入函数插入*/
118      insert1(p);
119       else
120       {
121      p->next=ready; /*创建就绪队列的第一个PCB*/
122      ready=p;
123       }
124    }
125    //clrscr();
126    printf("          优先算法的输出:\n");
127    printf("************************************************\n");
128    prt(alg);  /*输出进程PCB信息*/
129    run=ready; /*将就绪队列的第一个进程投入运行*/
130    ready=ready->next;
131    run->state='R';
132 }
133 /*轮转法创建进程PCB*/
134 void create2(char alg)
135 {
136    PCB *p;
137    int i,time;
138    char na[10];
139    ready=NULL;
140    finish=NULL;
141    run=NULL;
142    printf("输入进程的名称和运行时间:\n");
143    for(i=1;i<=N;i++)
144    {
145       p=malloc(sizeof(PCB));
146       scanf("%s",na);
147       scanf("%d",&time);
148       strcpy(p->name,na);
149       p->cputime=0;
150       p->needtime=time;
151       p->count=0; /*计数器*/
152       p->state='w';
153       p->round=3;  /*时间片*/
154       if(ready!=NULL)
155      insert2(p);
156 else
157       {
158      p->next=ready;
159      ready=p;
160      tail=p;
161       }
162    }
163    //clrscr();
164    printf("           简单时间片轮转输出     \n");
165    printf("************************************************\n");
166    prt(alg);   /*输出进程PCB信息*/
167    run=ready;  /*将就绪队列的第一个进程投入运行*/
168    ready=ready->next;
169    run->state='R';
170 }
171 /*优先数调度算法*/
172 priority(char alg)
173 {
174    while(run!=NULL)  /*当运行队列不空时,有进程正在运行*/
175    {
176       run->cputime=run->cputime+1;
177       run->needtime=run->needtime-1;
178       run->prio=run->prio-3; /*每运行一次优先数降低3个单位*/
179       if(run->needtime==0)  /*如所需时间为0将其插入完成队列*/
180       {
181      run->next=finish;
182      finish=run;
183      run->state='F';  /*置状态为完成态*/
184      run=NULL;  /*运行队列头指针为空*/
185      if(ready!=NULL) /*如就绪队列不空*/
186         firstin(); /*将就绪对列的第一个进程投入运行*/
187       }
188       else /*没有运行完同时优先数不是最大,则将其变为就绪态插入到就绪队列*/
189      if((ready!=NULL)&&(run->prio<ready->prio))
190      {
191         run->state='W';
192         insert1(run);
193         firstin(); /*将就绪队列的第一个进程投入运行*/
194      }
195       prt(alg); /*输出进程PCB信息*/
196    }
197 }
198 /*时间片轮转法*/
199 roundrun(char alg)
200 {
201    while(run!=NULL)
202    {
203       run->cputime=run->cputime+1;
204       run->needtime=run->needtime-1;
205       run->count=run->count+1;
206       if(run->needtime==0)/*运行完将其变为完成态,插入完成队列*/
207       {
208      run->next=finish;
209      finish=run;
210      run->state='F';
211      run=NULL;
212      if(ready!=NULL)
213         firstin(); /*就绪对列不空,将第一个进程投入运行*/
214       }
215       else
216      if(run->count==run->round)  /*如果时间片到*/
217      {
218         run->count=0;  /*计数器置0*/
219         if(ready!=NULL) /*如就绪队列不空*/
220         {
221            run->state='W'; /*将进程插入到就绪队列中等待轮转*/
222            insert2(run);
223            firstin(); /*将就绪对列的第一个进程投入运行*/
224         }
225      }
226             prt(alg); /*输出进程信息*/
227    }
228 }
229 /*主函数*/
230 main()
231 {
232    char flag;  /*算法标记*/
233    //clrscr();
234    printf("选择算法类型:P/R(优先算法/轮转法)\n");
235    scanf("%c",&flag); /*输入字符确定算法*/
236    printf("输入进程个数:\n");
237    scanf("%d",&N); /*输入进程数*/
238    if(flag=='P'||flag=='p')
239    {
240       create1(flag); /*优先数法*/
241       priority(flag);
242    }
243    else
244       if(flag=='R'||flag=='r')
245       {
246      create2(flag); /*轮转法*/
247      roundrun(flag);
248       }
249 }

6.运行截图

优先算法

轮转法

7.总结

      本次实验加深了我们在进程调度中对时间片轮转相关算法的理解,但实验对逻辑性要求很强,计算能力及综合性都较高,在实验编程时遇到了诸多困难。因此借鉴了网上的程序,此后还需加深对C语言的运用,并对进程调度算法进行巩固和加强。

posted on 2015-12-03 12:28  34郑伯瑜  阅读(544)  评论(0编辑  收藏  举报