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