《操作系统》实验报告——进程调度的模拟
生活随笔
收集整理的這篇文章主要介紹了
《操作系统》实验报告——进程调度的模拟
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
實驗內容
熟悉進程調度的各種算法,并對模擬程序給出數據和流程的詳細分析,之后畫出流程圖,最后參考模擬程序寫出時間片輪轉調度算法的程序。
實驗目的
通過本實驗,加深對進程調度算法原理和過程的理解。
實驗要求
(1) 對調度算法進行詳細分析,在仔細分析的基礎上,完全理解主要數據結構和過程的作用,給出主要數據結構的說明及畫出主要模塊的流程圖。
(2) 根據提示信息,把函數寫完整,使成為一個可運行程序。
?
(3) 反復運行程序,觀察程序執行的結果,驗證分析的正確性,然后給出一次執行的最后運行結果,并由結果計算出周轉時間和帶權周轉時間。
說明:進程生命周期數據。即CPU-I/O時間序列,它是進程運行過程中進行調度、進入不同隊列的依據。
如序列:10秒(CPU),500秒(I/O),20秒(CPU),100秒(I/O),30秒(CPU),90秒(I/O),110秒(CPU),60秒(I/O)……,此序列在進程創建時要求自動生成。
源代碼
#include <windows.h> #include<iostream> #include<fstream> #include <conio.h> #include <stdlib.h> #include <io.h> #include <string.h> #include <stdio.h> using namespace std; struct ProcStruct {int p_pid; // 進程的標識號char p_state; // 進程的狀態,C--運行 R--就緒 W--組塞 B--后備 F--完成int p_rserial[10]; // 模擬的進程執行的CPU和I/O時間數據序列,間隔存儲,第0項存儲隨后序列的長度(項數),以便知曉啥時該進程執行結束int p_pos; // 當前進程運行到的位置,用來記憶執行到序列中的哪項int p_starttime; // 進程建立時間int p_endtime; // 進程運行結束時間int p_cputime; // 當前運行時間段進程剩余的需要運行時間int p_iotime; // 當前I/O時間段進程剩余的I/O時間int p_next; // 進程控制塊的鏈接指針 } proc[10]; int RunPoint; // 運行進程指針,-1時為沒有運行進程 int WaitPoint; // 阻塞隊列指針,-1時為沒有阻塞進程 int ReadyPoint; // 就緒隊列指針,-1時為沒有就緒進程 long ClockNumber; // 系統時鐘 int ProcNumber; // 系統中模擬產生的進程總數 int FinishedProc; // 系統中目前已執行完畢的進程總數// 顯示進程數據序列void DisData() {ofstream outFile; //同時將該信息寫入磁盤的某txt文件中 ,該函數要#include <fstream.h>outFile.open("1_Process_Info.txt") ; //該txt 文件名可自己命名,第1次open時磁盤 中沒有該文件,系統會創建一個空白的。for(int i=0; i<ProcNumber; i++) { //寫到txt文件中outFile<< "ID=" << proc[i].p_pid <<"(len="<<proc[i].p_rserial[0]<<",start="<<proc[i].p_starttime<<"):";for(int j=1; j<=proc[i].p_rserial[0];j++)outFile<<" "<<proc[i].p_rserial[j];outFile<<"\n"; //打印到屏幕上 cout<< "ID=" << proc[i].p_pid <<"(len="<<proc[i].p_rserial[0]<<",start="<<proc[i].p_starttime<<"):";for(int j=1; j<=proc[i].p_rserial[0];j++)cout<<" "<<proc[i].p_rserial[j];cout<<"\n"; }outFile.close(); // 寫入txt文件的流被沖刷,保存到磁盤上 }// // // 隨機生成進程數量和每個CPU--I/O時間數據序列,進程數量控制在5到10之間, // // 數據序列控制在6到12之間,CPU和I/O的時間數據值在5到15的范圍 // // //void Create_ProcInfo(void ) {int s,i,j;srand(GetTickCount()); // 初始化隨機數隊列的"種子"ProcNumber=((float) rand() / 32767) * 5 + 5; // 隨機產生進程數量5~10FinishedProc=0;for(i=0;i<ProcNumber;i++) // 生成進程的CPU--I/O時間數據序列{ proc[i].p_pid=((float) rand() / 32767) * 1000;proc[i].p_state='B'; // 初始都為后備狀態s=((float) rand() / 32767) *6 + 6; // 產生的進程數據序列長度在6~12間proc[i].p_rserial[0]=s; // 第一項用于記錄序列的長度for(j=1;j<=s;j++) // 生成時間數據序列,數值在10~30間proc[i].p_rserial[j]=((float) rand() / 32767) *10 + 5;// 賦其他字段的值proc[i].p_pos=1;proc[i].p_starttime=((float) rand() / 32767) *49+1;proc[i].p_endtime=0; proc[i].p_cputime=proc[i].p_rserial[1]; proc[i].p_iotime=proc[i].p_rserial[2]; proc[i].p_next=-1; }printf("\n---------------------------\n 建立了%d個進程數據序列\n\n", ProcNumber);DisData();printf("\nPress Any Key To Continue.......");_getch() ; return ; }// 從磁盤讀取最后一次生成的進程信息的文件,執行調度,以重現調度情況。void Read_Process_Info() {ifstream inFile; // 定義打開文件的文件流char ch; int i,j,k,tmp; inFile.open("Process_Info.txt") ; // 打開上次寫的txt進行信息文件流i=0;while(inFile){ inFile.get(ch);for(j=0;j<3;j++) inFile.get(ch);//扔掉3個字符, inFile>>proc[i].p_pid;for(j=0;j<5;j++) inFile.get(ch);//繼續讀,扔掉5個字符inFile>>proc[i].p_rserial[0];for(j=0;j<7;j++) inFile.get(ch);//繼續讀,扔掉7個字符inFile>>proc[i].p_starttime;for(j=0;j<2;j++) inFile.get(ch);//繼續讀,扔掉2個字符for(k=1;k<=proc[i].p_rserial[0];k++){inFile>>tmp; proc[i].p_rserial[k]=tmp;} proc[i].p_state='B';proc[i].p_pos=1;proc[i].p_endtime=0; proc[i].p_next=-1; proc[i].p_cputime=proc[i].p_rserial[1]; proc[i].p_iotime=proc[i].p_rserial[2]; i++; //本行結束,一個進程信息讀完,序號+1, 準備 next process }ProcNumber=i-1; //給ProcNumber賦值,i最后有++,回位下inFile.close();//完工后,記得歸位,關燈。 }// 檢查是否有新進程到達,有則放入就緒隊列void NewReadyProc(void) { int n;for(int i=0; i<ProcNumber; i++) { if (proc[i].p_starttime == ClockNumber) // 進程進入時間達到系統時間,ClockNumber是當前的系統時間{ proc[i].p_state='R'; // 進程狀態修改為就緒 proc[i].p_next=-1; // 該進行即將要掛在隊列末尾,它肯定是尾巴,后面沒人的,所以先設置next=-1if (ReadyPoint==-1) // 如果當前就緒隊列無進程ReadyPoint=i;else // 如果就緒隊列有進程,放入隊列尾{ n=ReadyPoint; while(proc[n].p_next!=-1) n=proc[n].p_next; //找到原來隊伍中的尾巴proc[n].p_next=i; //掛在這個尾巴后面}}} }// 選擇下一個可以運行的進程void NextRunProcess(){if (ReadyPoint==-1) { RunPoint = -1; return;} // 就緒隊列也沒有等待的進程proc[ReadyPoint].p_state ='C'; RunPoint=ReadyPoint; proc[ReadyPoint].p_cputime =proc[ReadyPoint].p_rserial[proc[ReadyPoint].p_pos] ; ReadyPoint=proc[ReadyPoint].p_next;proc[RunPoint].p_next = -1; }// CPU調度void Cpu_Sched(void) { int n;if (RunPoint == -1) // 沒有進程在CPU上執行{ NextRunProcess(); return; }proc[RunPoint].p_cputime--; // 進程CPU執行時間減少1個時鐘單位if (proc[RunPoint].p_cputime > 0) return; // 還需要CPU時間,下次繼續,這次就返回了//如果不滿足以上>0的條件,就意味著=0,就不會自動返回,接著做以下事情。 // 進程完成本次CPU后的處理if (proc[RunPoint].p_rserial[0]==proc[RunPoint].p_pos) //進程全部序列執行完成{ FinishedProc++;proc[RunPoint].p_state ='F';proc[RunPoint].p_endtime = ClockNumber; RunPoint=-1; //無進程執行 NextRunProcess(); //找分派程序去,接著做下一個} else //進行IO操作,進入阻塞隊列{proc[RunPoint].p_pos++;proc[RunPoint].p_state ='W';proc[RunPoint].p_iotime =proc[RunPoint].p_rserial[proc[RunPoint].p_pos];proc[n].p_next == -1; //標記下,就自己一個進程,沒帶尾巴一起來;否則,當p_next不為-1時,后面的那一串都是被阻塞者n=WaitPoint;if(n == -1) //是阻塞隊列第一個I/O進程WaitPoint=RunPoint; else{ do //放入阻塞隊列第尾{if(proc[n].p_next == -1) { proc[n].p_next = RunPoint; break;}n=proc[n].p_next;} while(n!=-1) ;}RunPoint=-1; NextRunProcess(); }return; }// 顯示系統當前狀態void Display_ProcInfo( ) { int n;system("cls") ;printf("\n 當前系統模擬%2d個進程的運行時鐘:%ld\n\n", ProcNumber,ClockNumber);printf(" 就緒指針=%d, 運行指針=%d, 阻塞指針=%d\n\n",ReadyPoint,RunPoint,WaitPoint);if(RunPoint!= -1){//Print 當前運行的進程的信息;printf(" .............Running Process .............\n ");printf("當前運行的進程 No.%d ID:%d(%2d,%2d)", RunPoint,proc[RunPoint].p_pid,proc[RunPoint].p_rserial[0],proc[RunPoint].p_starttime);printf(" 總CPU時間=%d, 剩余CPU時間=%d\n",proc[RunPoint].p_rserial[proc[RunPoint].p_pos],proc[RunPoint].p_cputime);}elseprintf("No Process Running !\n");n=ReadyPoint;printf("\n Ready Process ...... \n");while(n!=-1) // 顯示就緒進程信息{printf(" [No.%2d ID:%4d],%d,%d,%d\n",n,proc[n].p_pid,proc[n].p_starttime,proc[n].p_rserial[proc[n].p_pos],proc[n].p_cputime );n=proc[n].p_next;}n=WaitPoint;printf("\n Waiting Process ...... \n");while(n!=-1) // 顯示阻塞進程信息{ printf(" [No.%2d ID:%4d],%d,%d,%d\n",n,proc[n].p_pid,proc[n].p_starttime,proc[n].p_rserial[proc[n].p_pos],proc[n].p_iotime);n=proc[n].p_next; }printf("\n=================== 后備進程 ====================\n");for(int i=0; i<ProcNumber; i++) if (proc[i].p_state=='B')printf(" [No.%2d ID:%4d],%d\n",i,proc[i].p_pid,proc[i].p_starttime); printf("\n================ 已經完成的進程 =================\n");for(int i=0; i<ProcNumber; i++) if (proc[i].p_state=='F')printf(" [No.%2d ID:%4d],%d,%d\n",i,proc[i].p_pid,proc[i].p_starttime,proc[i].p_endtime);}// I/O調度void IO_Sched(){int n,bk;if (WaitPoint==-1) return; // 沒有等待I/O的進程,直接返回proc[WaitPoint].p_iotime--; // 進行1個時鐘的I/O時間 if (proc[WaitPoint].p_iotime > 0) return; // 還沒有完成本次I/O// 進程的I/O完成處理if (proc[WaitPoint].p_rserial[0]==proc[WaitPoint].p_pos) //進程全部任務執行完成{ FinishedProc++;proc[WaitPoint].p_endtime = ClockNumber;proc[WaitPoint].p_state ='F';if(proc[WaitPoint].p_next==-1){ WaitPoint=-1;return ;}else //調度下一個進程進行I/O操作{n=proc[WaitPoint].p_next;proc[WaitPoint].p_next=-1;WaitPoint=n;proc[WaitPoint].p_iotime =proc[WaitPoint].p_rserial[proc[WaitPoint].p_pos] ;return ;}}else //進行下次CPU操作,進就緒隊列{bk=WaitPoint;WaitPoint=proc[WaitPoint].p_next;proc[bk].p_pos++;proc[bk].p_state ='R'; //進程狀態為就緒proc[bk].p_next =-1;n=ReadyPoint; if(n == -1) //是就緒隊列的第一個進程{ ReadyPoint=bk; return; } else{ do {if(proc[n].p_next == -1) { proc[n].p_next = bk; break ; }n=proc[n].p_next;}while(n!=-1); }}return ; }// 顯示模擬執行的結果void DisResult(){int i; printf("\n---------------------------------\n");printf("標識號-時間序列-建立時間-結束時間-周轉時間-帶權周轉時間\n");for(i=0; i<ProcNumber; i++) { printf("ID=%d -> %d\t",proc[i].p_pid ,proc[i].p_rserial[0] );printf("%d\t%d\t",proc[i].p_starttime,proc[i].p_endtime);printf("%d\t",proc[i].p_endtime-proc[i].p_starttime);int sumtime=0;for(int j=1; j<=proc[i].p_rserial[0];j++)sumtime+=proc[i].p_rserial[j];printf("%.2f",(proc[i].p_endtime-proc[i].p_starttime)*1.0/sumtime);printf("\n" );} }// 調度模擬算法void Scheduler_FF(void) //調度模擬算法 {if(ProcNumber==0) //該值居然是0? 只能說用戶沒創建進程{ Read_Process_Info();//那么,從磁盤讀取上次創建的進程信息,賦值給相應變量 }ClockNumber=0;// 時鐘開始計時, 開始調度模擬while(FinishedProc < ProcNumber){ // 執行算法ClockNumber++; // 時鐘前進1個單位NewReadyProc(); // 判別新進程是否到達Cpu_Sched(); // CPU調度IO_Sched(); // IO調度 Display_ProcInfo(); //顯示當前狀態Sleep(700); }DisResult(); _getch(); } ///// 主函數/// int main( ) {char ch; RunPoint=-1; // 運行進程指針,-1時為沒有運行進程WaitPoint=-1; // 阻塞隊列指針,-1時為沒有阻塞進程ReadyPoint=-1; // 就緒隊列指針,-1時為沒有就緒進程ClockNumber=0; // 系統時鐘ProcNumber=0; // 當前系統中的進程總數system("cls") ;while ( true ) {printf("***********************************\n");printf(" 1: 建立進程調度數據序列 \n") ;printf(" 2: 讀進程信息,執行調度算法\n") ; printf(" 3: 顯示調度結果 \n") ;printf(" 4: 退出\n") ;printf("***********************************\n");printf( "Enter your choice (1 ~ 4): "); do ch = (char)_getch() ; //如果輸入信息不正確,繼續輸入while(ch != '1' && ch != '2' && ch != '3'&& ch != '4');if(ch == '4') { printf( "\n");return 0; } // 選擇4,退出 else if(ch == '3') DisResult(); // 選擇3 else if(ch == '2') Scheduler_FF(); // 選擇2 else if(ch == '1') Create_ProcInfo(); // 選擇1 _getch() ; system("cls") ;}//結束printf("\nPress Any Key To Continue:");_getch() ;return 0; }運行結果
?
參考文章
操作系統實驗——進程調度的模擬
實驗4 進程調度的模擬
2011 操作系統 實驗4 進程調度的模擬(答案Part1)
2011 操作系統 實驗4 進程調度的模擬(答案Part2)
2011 操作系統 實驗4 進程調度的模擬(源程序)
總結
以上是生活随笔為你收集整理的《操作系统》实验报告——进程调度的模拟的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 《软件工程》实验报告——软件设计
- 下一篇: Spring Security——根据请