进程调度模拟算法
一、实验目的
进程调度是处理机管理的核心内容。本实验要求用高级语言编写模拟进程调度程序,以便加深理解有关进程控制快、进程队列等概念,并体会和了解优先数算法和时间片轮转算法的具体实施办法。
二、实验内容
1.设计进程控制块PCB 的结构,通常应包括如下信息:
进程名、进程优先数(或轮转时间片数)、进程已占用的CPU 时间、进程到完成还需要的时间、进程的状态、当前队列指针等。
2.编写两种调度算法程序:
优先数调度算法程序
循环轮转调度算法程序
3.按要求输出结果。
三、实验过程
(一)进程控制块结构如下:
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 结构和其他有关变量。
(四)运行和显示
程序开始运行后,首先提示:请用户选择算法,输入进程名和相应的NEEDTIME 值。
每次显示结果均为如下5 个字段:
name cputime needtime priority state
注: 1.在state 字段中,"R"代表执行态,"W"代表就绪(等待)态,"F"代表完成态。
2.应先显示"R"态的,再显示"W"态的,再显示"F"态的。
3.在"W"态中,以优先数高低或轮转顺序排队;在"F"态中,以完成先后顺序排队。
四、实验结果
• 上机调试
• 遇到的主要问题和解决方法
在利用指针处理时很困难,也经历了很艰难的过程,实验中设计了结构指针用来指向PCB结构,PCB结构中又有链表指针。
五、实验总结
通过本次试验对优先数调度算法和时间片轮转调度算法实现的过程,有了很清楚的认识、理解。随后通过设计PCB结构,模拟进程调度,加深了对进程的理解。
六、源代码
1 #include <stdio.h> 2 #include <stdlib.h> 3 #include <string.h> 4 #include<windows.h> 5 6 /*进程控制块数据结构*/ 7 typedef struct node 8 { 9 char name[10];/*进程名*/ 10 int prio; /*进程优先级*/ 11 int round; /*循环轮转法进程每次轮转的时间片*/ 12 int cputime; /*进程累计消耗的CUP时间*/ 13 int needtime; /*进程到完成还需要的CUP时间*/ 14 int count; /*循环轮转法一个是时间片内进程运行时间*/ 15 char state; /*进程的状态:'R':运行,'W':等待,'F':结束*/ 16 struct node *next;/*指向下一个进程的链指针*/ 17 }PCB; 18 19 PCB *finish,*ready,*tail,*run;/*指向三个队列的队首的指针, 20 finish为完成队列头指针, 21 ready为就绪队列头指针, 22 tail为就绪队列的队尾指针, 23 run为当前运行进程头指针*/ 24 25 int N;/*定义进程的数目*/ 26 27 28 void firstin(void); //调度就绪队列的第一个进程投入运行; 29 void print1(char a); //打印表头行信息 30 void print2(char chose,PCB *p); //打印每一行的状态信息 31 void print(char chose); //打印每执行一次算法后所有的进程的状态信息 32 void insert_prio(PCB *q); //在优先数算法中,将尚未完成的PCB按优先数顺序插入到就绪队列中; 33 void prior_init(char chose); //进程优先级法初始化将进程按优先级插入到就绪队列里 34 void priority(char chose); //进程优先级算法总函数 35 void insert_rr(PCB *q); //在轮转法中,将执行了一个时间片单位(为2),但尚未完成的进程的PCB,插到就绪队列的队尾; 36 void roundrun_init(char chose); //循环轮转法初始化将就绪队列保存为FIFO队列 37 void roundrun(char chose); //循环轮转法总算法 38 39 40 41 42 43 void main()//主函数 44 { 45 char chose=' '; 46 while((chose!='q')&&(chose!='Q')) 47 { 48 fflush(stdin); 49 printf("选择进程优先级算法请输入P,选择循环轮转算法请输入R,退出请输入Q "); 50 printf("请输入你的选择:"); 51 scanf("%c",&chose); 52 if((chose!='q')&&(chose!='Q')) 53 { 54 system("cls"); 55 if((chose=='P')||(chose=='p')) 56 { 57 58 prior_init(chose); 59 priority(chose); 60 system("cls"); 61 } 62 63 else if((chose=='r')||(chose=='R')) 64 { 65 66 roundrun_init(chose); 67 roundrun(chose); 68 system("cls"); 69 70 } 71 } 72 } 73 printf("谢谢使用! "); 74 } 75 76 void firstin(void)//调度就绪队列的第一个进程投入运行; 77 { 78 if(ready!=NULL) 79 { 80 run=ready; 81 ready=ready->next; 82 run->state='R'; 83 run->next=NULL; 84 } 85 else 86 { 87 run=NULL; 88 89 } 90 91 } 92 93 94 95 96 97 98 99 100 void print1(char a)//打印表头行信息 101 { 102 if(toupper(a)=='P') 103 { 104 printf("name cputime needtime priority state "); 105 } 106 else 107 { 108 printf("name cputime needtime count round state "); 109 } 110 } 111 112 113 114 115 116 117 118 119 void print2(char chose,PCB *p)//打印每一行的状态信息 120 { 121 if(toupper(chose)=='P') 122 { 123 printf("%s %d %d %d %c ",p->name,p->cputime,p->needtime,p->prio,p->state); 124 125 } 126 else 127 { 128 printf("%s %d %d %d %d %c ",p->name,p->cputime,p->needtime,p->count,p->round,p->state); 129 } 130 } 131 void print(char chose)//打印每执行一次算法后所有的进程的状态信息 132 { 133 PCB *p; 134 print1(chose); 135 if(run!=NULL) 136 { 137 print2(chose,run); 138 } 139 140 p=ready; 141 while(p!=NULL) 142 { 143 print2(chose,p); 144 p=p->next; 145 } 146 147 p=finish; 148 while(p!=NULL) 149 { 150 print2(chose,p); 151 p=p->next; 152 } 153 154 } 155 void insert_prio(PCB *q)/*在优先数算法中,将尚未 156 完成的PCB按优先数顺序插入到就绪队列中;*/ 157 { 158 PCB *p,*s,*r; /*p,r用来控制就绪队列滚动,S指向插入的队列*/ 159 160 s=q; 161 p=ready; 162 r=p; 163 164 if(s->prio>ready->prio)// 要插入的进程的优先级大于ready的优先级 165 { 166 s->next=ready; 167 ready=s; 168 } 169 else//要插入的进程的优先级不大于ready的优先级 170 { 171 while(p) 172 { 173 if(p->prio>=s->prio) 174 { 175 r=p; 176 p=p->next; 177 } 178 else 179 break; 180 181 } //找到要插入的位置 182 s->next=p; 183 r->next=s; 184 } 185 } 186 187 188 189 void prior_init(char chose)/*进程优先级法初始化 190 将进程按优先级插入到就绪队列里*/ 191 { 192 PCB *p; 193 int i,time; 194 char na[10]; 195 ready=NULL; 196 finish=NULL; 197 run=NULL; 198 printf("输入进程 的个数 N: "); 199 scanf("%d",&N); 200 for(i=0;i<N;i++) 201 { 202 p=(PCB*)malloc(sizeof(PCB)); 203 printf("输入第%d个进程名 ",i+1); 204 scanf("%s",na); 205 printf("完成进程需要的时间片数 "); 206 scanf("%d",&time); 207 strcpy(p->name,na); 208 p->cputime=0; 209 p->needtime=time; 210 p->state='W'; 211 p->prio=50-time;//设置进程优先值初值 212 213 if(ready==NULL) 214 { 215 ready=p; 216 ready->next=NULL; 217 } 218 else 219 { 220 insert_prio(p); 221 } 222 printf("当前就绪队列的进程的信息 "); 223 print(chose); 224 } 225 printf("%d个进程已按优先级从高到低进到就绪队列中 ",N); 226 printf("按回车键开始模拟优先级算法..... "); 227 fflush(stdin); 228 getchar(); 229 firstin(); 230 } 231 void priority(char chose)//进程优先级算法总函数 232 { 233 int i=1; 234 235 while(run!=NULL) 236 { 237 run->cputime+=1; 238 run->needtime-=1; 239 run->prio-=1; 240 if(run->needtime==0) 241 { 242 run->next=finish; 243 finish=run; 244 run->state='F'; 245 run->prio=0; 246 run=NULL; 247 firstin(); 248 } 249 else 250 { 251 if((ready!=NULL)&&(run->prio<ready->prio)) 252 { 253 run->state='W'; 254 insert_prio(run); 255 run=NULL; 256 firstin(); 257 } 258 } 259 260 261 print(chose); 262 263 264 } 265 266 getchar(); 267 } 268 void insert_rr(PCB *q)//在轮转法中,将执行了一个时间片单位(为2), 269 //但尚未完成的进程的PCB,插到就绪队列的队尾; 270 { 271 tail->next=q; 272 tail=q; 273 q->next=NULL; 274 } 275 void roundrun_init(char chose)/*循环轮转法初始化 276 将就绪队列保存为FIFO队列*/ 277 { 278 PCB *p; 279 int i,time; 280 char na[10]; 281 ready=NULL; 282 finish=NULL; 283 run=NULL; 284 printf(" 循环轮转算法模拟全过程 "); 285 printf("输入进程 的个数 N: "); 286 scanf("%d",&N); 287 for(i=0;i<N;i++) 288 { 289 p=(PCB*)malloc(sizeof(PCB)); 290 printf("输入第%d个进程名 ",i+1); 291 scanf("%s",na); 292 printf("完成进程需要的时间片数 "); 293 scanf("%d",&time); 294 strcpy(p->name,na); 295 p->cputime=0; 296 p->needtime=time; 297 p->count=0; 298 p->state='W'; 299 p->round=2; 300 if(ready!=NULL) 301 { 302 insert_rr(p); 303 } 304 else 305 { 306 p->next=ready; 307 ready=p; 308 tail=p; 309 } 310 printf("当前就绪队列的进程的信息 "); 311 print(chose); 312 } 313 printf("%d个进程已按FIFO进到就绪队列中 ",N); 314 printf("按回车键开始模循环轮转算法..... "); 315 fflush(stdin); 316 getchar(); 317 run=ready; 318 ready=ready->next; 319 run->state='R'; 320 321 } 322 void roundrun(char chose)//循环轮转法总算法 323 { 324 int i=1; 325 while(run!=NULL) 326 { 327 run->cputime+=1; 328 run->needtime-=1; 329 run->count+=1; 330 if(run->needtime==0) 331 { 332 run->next=finish; 333 finish=run; 334 run->state='F'; 335 run->prio=0; 336 run=NULL; 337 if(ready!=NULL) 338 { 339 firstin(); 340 } 341 } 342 else 343 { 344 if(run->count==run->round) 345 { 346 run->count=0; 347 if(ready!=NULL) 348 { 349 run->state='W'; 350 insert_rr(run); 351 firstin(); 352 } 353 } 354 } 355 356 print(chose); 357 358 359 } 360 getchar(); 361 362 }