操作系統,時間片輪轉算法的C語言實現Round Robin


  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 }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM