1 #include "windows.h" 2 #include <conio.h> 3 #include <stdlib.h> 4 #include <fstream.h> 5 #include <io.h> 6 #include <string.h> 7 #include <stdio.h> 8 9 void Create_ProcInfo(); // 建立进程调度需要的数据 10 void Display_ProcInfo(); // 显示当前系统全部进程的状态 11 void Scheduler_FF(); 12 void Cpu_Sched(); 13 void IO_Sched(); 14 void NextRunProcess(); 15 void DisData(); 16 void DisResult(); 17 18 int RunPoint; // 运行进程指针,-1时为没有运行进程 19 int WaitPoint; // 阻塞队列指针,-1时为没有阻塞进程 20 int ReadyPoint; // 就绪队列指针,-1时为没有就绪进程 21 long ClockNumber; // 系统时钟 22 int ProcNumber; // 系统中模拟产生的进程总数 23 int FinishedProc; // 系统中模拟产生的进程总数 24 int q=9;//时间片 25 26 27 //进程信息结构 28 struct ProcStruct 29 { 30 int p_pid; // 进程的标识号 31 char p_state; // 进程的状态,C--运行 R--就绪 W--组塞 B--后备 F--完成 32 int p_rserial[16]; // 模拟的进程执行的CPU和I/O时间数据序列,间隔存储,0项存储有效项数 33 int p_pos; // 当前进程运行到的序列位置 34 int p_starttime; // 进程建立时间 35 int p_endtime; // 进程运行结束时间 36 int p_cputime; // 当前运行时间段进程剩余的需要运行时间 37 int p_iotime; // 当前I/O时间段进程剩余的I/O时间 38 int p_next; // 进程控制块的链接指针 39 int p_excutetime; // 记录一次时间片内执行的时间 40 } proc[10]; 41 42 //////////////////////////////////////////////////////////////////////////// 43 // 44 // 随机生成进程数量和每个CPU--I/O时间数据序列,进程数量控制在5到10之间, // 45 // 数据序列控制在6到12之间,CPU和I/O的时间数据值在5到15的范围 // 46 // 47 //////////////////////////////////////////////////////////////////////////// 48 49 void Create_ProcInfo(void ) 50 { 51 int s,i,j; 52 53 srand(GetTickCount()); // 初始化随机数队列的"种子" 54 ProcNumber=((float) rand() / 32767) * 5 ; // 随机产生进程数量5~10 55 56 57 for(i=0;i<ProcNumber;i++) // 生成进程的CPU--I/O时间数据序列 58 { 59 proc[i].p_pid=((float) rand() / 32767) * 1000; 60 proc[i].p_state=\'B\'; // 初始都为后备状态 61 62 s=((float) rand() / 32767) *6 + 2; // 产生的进程数据序列长度在6~12间 63 proc[i].p_rserial[0]=s; // 第一项用于记录序列的长度 64 for(j=1;j<=s;j++) // 生成时间数据序列 65 proc[i].p_rserial[j]=((float) rand() / 32767) *10 + 5; 66 // 赋其他字段的值 67 proc[i].p_pos=1; 68 proc[i].p_starttime=((float) rand() / 32767) *49+1; // 随机设定进程建立时间 69 proc[i].p_endtime=0; 70 proc[i].p_cputime=proc[i].p_rserial[1]; 71 proc[i].p_iotime=proc[i].p_rserial[2]; 72 proc[i].p_next=-1; 73 proc[i].p_excutetime=0; 74 } 75 printf("\n---------------------------\n 建立了%2d 个进程数据序列\n\n", ProcNumber); 76 DisData(); 77 printf("\nPress Any Key To Continue......."); 78 _getch() ; 79 return ; 80 } 81 82 //////////////////////////////////////////////////////////////////////// 83 84 // 显示系统当前状态 85 86 //////////////////////////////////////////////////////////////////////// 87 88 void Display_ProcInfo(void) 89 { int i,n; 90 91 system("cls") ; 92 printf("时间片为%d",q); 93 printf("\n 当前系统模拟%2d 个进程的运行 时钟:%ld\n\n", ProcNumber,ClockNumber); 94 95 printf(" 就绪指针=%d, 运行指针=%d, 阻塞指针=%d\n\n",ReadyPoint,RunPoint,WaitPoint ); 96 if(RunPoint!= -1) 97 { 98 printf(" 当前运行的进程 No.%d ID:%d\n", RunPoint,proc[RunPoint].p_pid); 99 printf(" %6d,%6d,%6d\n",proc[RunPoint].p_starttime,proc[RunPoint].p_rserial[proc[RunPoint].p_pos],proc[RunPoint].p_cputime); 100 printf("当前运行的进程执行的时间为%d",proc[RunPoint].p_excutetime); 101 printf("当前运行的进程执行的cpu时间为%d",proc[RunPoint].p_cputime); 102 } 103 else 104 printf(" 当前运行的进程ID:No Process Running !\n"); 105 106 n=ReadyPoint; 107 printf("\n Ready Process ...... \n"); 108 while(n!=-1) // 显示就绪进程信息 109 { 110 printf(" No.%d ID:%5d,%6d,%6d,%6d\n",n,proc[n].p_pid,proc[n].p_starttime,proc[n].p_rserial[proc[n].p_pos],proc[n].p_cputime ); 111 n=proc[n].p_next; 112 } 113 114 n=WaitPoint; 115 printf("\n Waiting Process ...... \n"); 116 while(n!=-1) // 显示阻塞进程信息 117 { 118 printf(" No.%d ID:%5d,%6d,%6d,%6d\n",n,proc[n].p_pid,proc[n].p_starttime,proc[n].p_rserial[proc[n].p_pos],proc[n].p_iotime); 119 n=proc[n].p_next; 120 } 121 122 printf("\n=================== 后备进程 ====================\n"); 123 for(i=0; i<ProcNumber; i++) 124 if (proc[i].p_state==\'B\') 125 printf(" No.%d ID:%5d,%6d\n",i,proc[i].p_pid,proc[i].p_starttime); 126 127 printf("\n================ 已经完成的进程 =================\n"); 128 for(i=0; i<ProcNumber; i++) 129 if (proc[i].p_state==\'F\') 130 printf("No.%d ID:%5d,%6d,%6d\n",i,proc[i].p_pid,proc[i].p_starttime,proc[i].p_endtime); 131 132 } 133 134 //////////////////////////////////////////////////////////////////////// 135 136 // 显示模拟执行的结果 137 138 //////////////////////////////////////////////////////////////////////// 139 void DisResult(void) 140 { int i; 141 printf("\n---------------------------------\n"); 142 for(i=0; i<ProcNumber; i++) 143 { 144 printf("ID=%4d> %2d ",proc[i].p_pid ,proc[i].p_rserial[0] ); 145 printf("%4d,%4d",proc[i].p_starttime,proc[i].p_endtime); 146 printf("\n" ); 147 } 148 } 149 150 //////////////////////////////////////////////////////////////////////// 151 152 // 显示进程数据序列 153 154 //////////////////////////////////////////////////////////////////////// 155 void DisData(void) 156 { int i,j; 157 158 for(i=0; i<ProcNumber; i++) 159 { 160 printf("ID=%4d %2d > ",proc[i].p_pid ,proc[i].p_rserial[0] ); 161 for(j=1; j<=proc[i].p_rserial[0];j++) 162 printf("%4d",proc[i].p_rserial[j]); 163 printf("\n" ); 164 } 165 } 166 //////////////////////////////////////////////////////////////////////// 167 168 // 选择下一个可以运行的进程 169 170 //////////////////////////////////////////////////////////////////////// 171 void NextRunProcess(void) 172 { 173 if (ReadyPoint==-1) { RunPoint = -1; return;} // 就绪队列也没有等待的进程 174 175 proc[ReadyPoint].p_state =\'C\'; //ReadyPoint所指示的进程状态变为执行状态 176 RunPoint=ReadyPoint; 177 if( proc[ReadyPoint].p_excutetime==-1)//进程为执行成功,接着上次的cpu时间执行 178 { 179 proc[ReadyPoint].p_excutetime=0; 180 } 181 else 182 proc[ReadyPoint].p_cputime =proc[ReadyPoint].p_rserial[proc[ReadyPoint].p_pos] ; 183 ReadyPoint=proc[ReadyPoint].p_next; 184 proc[RunPoint].p_next = -1; 185 186 } 187 //////////////////////////////////////////////////////////////////////// 188 189 // CPU调度 190 191 //////////////////////////////////////////////////////////////////////// 192 193 void Cpu_Sched(void) 194 { 195 int n; 196 197 if (RunPoint == -1) // 没有进程在CPU上执行 198 { NextRunProcess(); return; } 199 200 proc[RunPoint].p_cputime--; // 进程CPU执行时间减少1个时钟单位 201 proc[RunPoint].p_excutetime++; 202 if((proc[RunPoint].p_cputime == 0&&proc[RunPoint].p_excutetime<=q))//若时间片未完,但进程已经结束 203 { 204 //printf("若时间片未完,但进程已经结束\n"); 205 proc[RunPoint].p_excutetime=0;//清空运行时间 206 // 进程完成本次CPU后的处理 207 if (proc[RunPoint].p_rserial[0]==proc[RunPoint].p_pos) //进程全部序列执行完成 208 { 209 FinishedProc++; 210 proc[RunPoint].p_state =\'F\'; 211 proc[RunPoint].p_endtime = ClockNumber; 212 RunPoint=-1; //无进程执行 213 NextRunProcess(); 214 } 215 else //进行IO操作,进入阻塞队列 216 { 217 proc[RunPoint].p_pos++; 218 proc[RunPoint].p_state =\'W\'; 219 proc[RunPoint].p_iotime =proc[RunPoint].p_rserial[proc[RunPoint].p_pos]; 220 printf("进入阻塞队列\n"); 221 n=WaitPoint; 222 if(n == -1) //是阻塞队列第一个I/O进程 223 WaitPoint=RunPoint; 224 else 225 { do //放入阻塞队列第尾 226 { 227 if(proc[n].p_next == -1) 228 { proc[n].p_next = RunPoint; 229 break; 230 } 231 n=proc[n].p_next; 232 } while(n!=-1) ; 233 } 234 RunPoint=-1; 235 NextRunProcess(); 236 } 237 return; 238 } 239 if(proc[RunPoint].p_cputime > 0&&proc[RunPoint].p_excutetime<q)//时间片未完 程序未执行结束 继续执行 240 { 241 //printf("时间片未完 程序未执行结束 继续执行\n"); 242 return; 243 } 244 //{ printf("\n RunPoint=%d,ctime=%d",RunPoint,proc[RunPoint].p_cputime);getchar();return; } 245 if(proc[RunPoint].p_cputime > 0&&proc[RunPoint].p_excutetime==q)//时间片完,但是程序未执行完 放到就绪队列尾部 246 { 247 //printf("时间片完,但是程序未执行完 放到就绪队列尾部\n"); 248 int n; 249 proc[RunPoint].p_state=\'R\'; // 进程状态修改为就绪 250 proc[RunPoint].p_next=-1; 251 proc[RunPoint].p_excutetime=-1;//清空运行时间,-1代表程序未执行完成 252 if(ReadyPoint==-1) // 就绪队列无进程 253 ReadyPoint=RunPoint; 254 else // 就绪队列有进程,放入队列尾 255 { 256 n=ReadyPoint; 257 while(proc[n].p_next!=-1) n=proc[n].p_next; 258 proc[n].p_next=RunPoint; 259 } 260 RunPoint=-1; 261 NextRunProcess(); //执行下一个进程 262 } 263 264 } 265 266 267 268 //////////////////////////////////////////////////////////////////////// 269 270 // I/O调度 271 272 //////////////////////////////////////////////////////////////////////// 273 274 void IO_Sched(void) 275 { 276 int n,bk; 277 278 if (WaitPoint==-1) return; // 没有等待I/O的进程,直接返回 279 280 proc[WaitPoint].p_iotime--; // 进行1个时钟的I/O时间 281 282 if (proc[WaitPoint].p_iotime > 0) return; // 还没有完成本次I/O 283 284 // 进程的I/O完成处理 285 if (proc[WaitPoint].p_rserial[0]==proc[WaitPoint].p_pos) //进程全部任务执行完成 286 { 287 FinishedProc++; 288 proc[WaitPoint].p_endtime = ClockNumber; 289 proc[WaitPoint].p_state =\'F\'; 290 291 if(proc[WaitPoint].p_next==-1) 292 { WaitPoint=-1;return ;} 293 else //调度下一个进程进行I/O操作 294 { 295 n=proc[WaitPoint].p_next; 296 proc[WaitPoint].p_next=-1; 297 WaitPoint=n; 298 proc[WaitPoint].p_iotime =proc[WaitPoint].p_rserial[proc[WaitPoint].p_pos] ; 299 return ; 300 } 301 } 302 else //进行下次CPU操作,进就绪队列 303 { 304 bk=WaitPoint; 305 WaitPoint=proc[WaitPoint].p_next; 306 307 proc[bk].p_pos++; 308 proc[bk].p_state =\'R\'; //进程状态为就绪 309 proc[bk].p_cputime = proc[bk].p_rserial[proc[bk].p_pos]; 310 proc[bk].p_next =-1; 311 312 n=ReadyPoint; 313 if(n == -1) //是就绪队列的第一个进程 314 { ReadyPoint=bk; return; } 315 else 316 { do 317 { 318 if(proc[n].p_next == -1) { proc[n].p_next = bk; break ; } 319 n=proc[n].p_next; 320 } 321 while(n!=-1); 322 } 323 } 324 return ; 325 } 326 327 328 329 330 331 //////////////////////////////////////////////////////////////////////// 332 333 // 检查是否有新进程到达,有则放入就绪队列 334 335 //////////////////////////////////////////////////////////////////////// 336 337 void NewReadyProc(void) 338 { 339 int i,n; 340 341 for(i=0; i<ProcNumber; i++) 342 { 343 if (proc[i].p_starttime == ClockNumber) // 进程进入时间达到系统时间 344 { 345 proc[i].p_state=\'R\'; // 进程状态修改为就绪 346 proc[i].p_next=-1; 347 348 if(ReadyPoint==-1) // 就绪队列无进程 349 ReadyPoint=i; 350 else // 就绪队列有进程,放入队列尾 351 { 352 n=ReadyPoint; 353 while(proc[n].p_next!=-1) n=proc[n].p_next; 354 proc[n].p_next=i; 355 } 356 } 357 } // for 358 return; 359 } 360 361 362 //////////////////////////////////////////////////////////////////////// 363 364 // 调度模拟算法 365 366 //////////////////////////////////////////////////////////////////////// 367 368 void Scheduler_FF(void) 369 { 370 FinishedProc=0; 371 if(ProcNumber==0) 372 { printf(" 必须首先建立进程调度数据 ! \n"); 373 system("cls"); return; 374 } 375 376 ClockNumber=0;// 时钟开始计时, 开始调度模拟 377 while(FinishedProc < ProcNumber) // 执行算法 378 { 379 ClockNumber++; // 时钟前进1个单位 380 NewReadyProc(); // 判别新进程是否到达 381 Cpu_Sched(); // CPU调度 382 IO_Sched(); // IO调度 383 Display_ProcInfo(); //显示当前状态 384 } 385 DisResult(); 386 getch(); return; 387 } 388 389 void Change_q(void) 390 { 391 scanf("%d",&q); 392 } 393 394 /////////////////////////////////////////////////////////////////// 395 396 // 主函数 397 398 /////////////////////////////////////////////////////////////////// 399 400 int main(int argc, char* argv[]) 401 { 402 char ch; 403 404 RunPoint=-1; // 运行进程指针,-1时为没有运行进程 405 WaitPoint=-1; // 阻塞队列指针,-1时为没有阻塞进程 406 ReadyPoint=-1; // 就绪队列指针,-1时为没有就绪进程 407 ClockNumber=0; // 系统时钟 408 ProcNumber=0; // 当前系统中的进程总数 409 410 system("cls") ; 411 while ( true ) 412 { 413 printf("***********************************\n"); 414 printf(" 1: 建立进程调度数据序列 \n") ; 415 printf(" 2: 执行调度算法\n") ; 416 printf(" 3: 显示调度结果 \n") ; 417 printf(" 4: 更改时间片 \n"); 418 printf(" 5: 退出\n") ; 419 printf("***********************************\n"); 420 printf( "Enter your choice (1 ~ 5): "); 421 422 do{ //如果输入信息不正确,继续输入 423 ch = (char)_getch() ; 424 } while(ch != \'1\' && ch != \'2\'&& ch != \'3\'&& ch != \'4\'&& ch != \'5\'); 425 426 if(ch == \'5\') { printf( "\n");return 0; } // 选择4,退出 427 if(ch == \'3\') DisResult(); // 选择3 428 if(ch == \'2\') Scheduler_FF(); // 选择2 429 if(ch == \'1\') Create_ProcInfo(); // 选择1 430 if(ch == \'4\') Change_q(); 431 _getch() ; 432 system("cls") ; 433 } 434 //结束 435 printf("\nPress Any Key To Continue:"); 436 _getch() ; 437 return 0; 438 }
操作系统,时间片轮转算法的C语言实现Round Robin
内容版权声明:除非注明,否则皆为本站原创文章。