实验三 进程调度模拟程序
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语言的运用,并对进程调度算法进行巩固和加强。