第一篇:操作系統實驗報告(讀者寫著問題,時間片輪轉算法,內存的分配,進程的調度)
小心
計算機專業類課程
實驗報告 課程名稱:操作系統 學
院:軟件學院 專
業:軟件工程 學生姓名:李 希
學
號:2010231020018 指導教師:丁老師
日
期: 2012年5月5日
電子科技大學計算機學院實驗中心
電 子 科 技 大 學
實
驗
報
告
實驗一
一、實驗名稱: 進程管理
二、實驗學時:4
三、實驗內容和目的: 實驗內容:(1)進程的創建
寫一段源程序,創建兩個進程,當此程序運行時,在系統中有一個父進程和兩個子進程活動。讓每一個進程在屏幕上顯示字符。觀察紀錄屏幕上的顯示結果,然后分析原因。(2)進程的控制
修改編寫的程序,將每個進程輸出一個字符改為每個進程輸出一句話,在觀察程序執行時屏幕出現的現象,并分析原因。實驗目的:
(1)加深對進程概念的理解,明確進程和程序的區別。
(2)進一步認識并發執行的實質。
(3)分析進程競爭資源現象,學習解決進程互斥的方法。
四、實驗原理:
利用fork函數來創建子進程,并返回子進程的ID號。
利用lockf函數來實現信號量對進程的資源競爭的調度,和互斥的方法。
五、實驗器材(設備、元器件):
一臺裝有VS2010的電腦,操作系統為WIN7.六、實驗步驟:
(1)先寫好2個子進程程序,并且讓2個子程序在屏幕上分別打印出A,B(2)父進程創建2個子進程,并在屏幕上打印出C。(3)觀察進程競爭資源的現象。
七、實驗數據及結果分析:
電子科技大學計算機學院實驗中心 子進程A的代碼:
#include
cout<<“I'm Process A/n”< } 子進程B的代碼: #include cout<<“I'm Process B”< //#include “stdafx.h” #include void print_error(){ DWORD nErrorNo = GetLastError();LPSTR lpBuffer; FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_SYSTEM,NULL,nErrorNo,LANG_NEUTRAL,(LPTSTR)& lpBuffer,0 , NULL);if(lpBuffer == NULL) | } { } printf(“%s(%d).n”, lpBuffer, nErrorNo);lpBuffer = “Sorry, cannot find this error info.”;int fork(const char* pszApplication,HANDLE& hProcess) { STARTUPINFO si={sizeof(si)}; } void lockf(HANDLE hObj){ } int main(int argc, char* argv[]){ HANDLE hProcess1,hProcess2;int child1=fork(“C:操¨′作á??系|ì統a3實o|ì驗¨|ProcessADebugProcessA.exe”,hProcess1);if(-1==child1) } lockf(hProcess1);cout << “fork error!n”;return-1;{ case WAIT_OBJECT_0: } printf(“nProcess exit.n”);break;printf(“nTime out.n”);break;printf(“nWait Failed.n”);print_error();break;DWORD state = WaitForSingleObject(hObj,INFINITE);switch(state)PROCESS_INFORMATION pi;if(!CreateProcess(pszApplication,NULL,NULL,NULL,FALSE,0,NULL,NULL,&si,&pi)){ } hProcess=pi.hProcess;return pi.dwProcessId;return-1;else case WAIT_TIMEOUT: case WAIT_FAILED: { 電子科技大學計算機學院實驗中心 } int child2=fork(“C:操¨′作á??系|ì統a3實o|ì驗¨|ProcessBDebugProcessB.exe”,hProcess2);if(-1==child2){ } cout<<“This is Process Cn”;lockf(hProcess2);return 0;cout << “fork error!n”;return-1;程序運行的結果: 八、實驗結論、心得體會和改進建議: 實驗結論:成功的通過了父進程C來創建了2個子進程A,B,并成功的對子進程進行了調度與管理。 心得體會:通過對進程的創建,調度,更加深了我們對操作系統這門課的進程的了解,而且也鍛煉了我們寫代碼的能力,和解決問題的能力。 改進建議:對于我們大二沒有接觸過Windows編程的學生來說,可能一些Windows的API函數不夠了解,以至于比較難理解老師給出的參考代碼。所以我希望,老師以后可以先給我們大家簡單的講解,介紹一下比較實用的Windows編程的API的函數。 實驗二 一、實驗名稱: 處理器調度 二、實驗學時:4 三、實驗內容和目的: 實驗內容: (1)假定系統有五個進程,每一個進程用一個進程控制塊PCB來代表。 電子科技大學計算機學院實驗中心 PCB的格式為: 其中,進程名——作為進程的標識,假設五個進程的進程名分別為1,2,3,4,5指針——進程按順序排成循環隊列,用指針指出下一個進程的進程控制塊的首地址,最后一個進程的指針指出第一個進程的進程控制塊首地址。要求運行時間——假設進程需要運行的單位時間數。已運行時間——假設進程已經運行的單位時間數,初始值為“0”。狀態——有兩種狀態,“ready”和“end”,初始狀態都為“ready”,用“ready”表示。當一個進程運行結束后,它的狀態為“end”,用“end”表示。 (2)每次運行所設計的處理器調度程序前,為每個進程任意確定它的“要求運行時間”。 (3)把五個進程按順序排成循環隊列,用指針指出隊列連接情況。另用一標志單元記錄輪到運行的進程。例如,當前輪到2執行,則有: (4)處理器調度總是選擇標志單元指示的進程運行。由于本實驗是模擬處理器調度的功能,對被選中的進程并不實際的啟動運行,而 是執行:已運行時間+1來模擬進程的一次運行,表示進程運行過一個單位的時間。 (5)進程運行一次后,把該進程的進程控制塊中的指針值送到標志單元,指示下一個輪到運行的進程。同時應判斷該進程的要求運行時間與已運行時間,若該進程的要求運行時間?已運行時間,則表示它尚未執行結束,應待到下一輪時再運行。若該進程的要求運行時間等于已運行時間,則表示它已經執行結束,應把它的狀態修改成“結束”(end)且退出隊列。此時,應把該進程的進程控制塊中的指針值送到前面一個進程的指針位置。 (6)若“ready”狀態的進程隊列不為空,則重復上面的(4)和(5) 電子科技大學計算機學院實驗中心 的步驟,直到所有的進程都成為“ready”狀態。 (7)在所設計的程序中 應有顯示或打印語句,能顯示或打印 每次選中進程的進程名以 及運行一次后進程 隊列的變化。 (8)為N個進程任意確定一組“要求運行時間”,啟動所設計的處理器調度程序,顯示或打印逐次被選中的進程名以及進程控制塊的動態變化過程。實驗目的: 在用多道程序設計的系統中,往往有若干個進程同時處于就緒狀態。所以當就緒進程個數大于處理器數時,就必須依照某種策略來決定哪些進程優先占用CPU。本實驗模擬在單處理器情況下的處理器調度,加深了解處理器調度的工作。 四、實驗原理: 定義進程PCB結構體。并用采用C++中的指針形成循環鏈表,并對鏈表中的結構進行操作。來模仿時間片輪轉的進程調度。 五、實驗器材(設備、元器件): 一臺裝有VS2010的電腦,操作系統為WIN7.六、實驗步驟:(1)定義結構體PCB:里面有進程的編號,執行需要的時間,和已經運行時間,還有進程的狀態信息。 (2)定義循環的單鏈表,來使結構都串聯起來。 (3)使用時間片輪轉的方法來動態地進行進程模擬的調度。(4)如果所有的進程都執行完畢,則退出程序。 七、實驗數據及結果分析: 實驗程序的代碼如下: #include struct Process{ }; struct Process *CreateList(int n)//初始化鏈表,并返回指向鏈表頭的指針 { struct Process *head=NULL,*tail=NULL;for(int i=1;i<=n;i++){ if(i==1){ head=new Process;tail=head;head->Name=i;head->RunTime=0;int Name;string Statu;int NeedTime;int RunTime;Process *Next; 電子科技大學計算機學院實驗中心 } } head->Statu=“Ready”;cout<<“請輸入”<>tail->NeedTime;} if(i!=1&&i!=n){ tail->Next=new Process;tail=tail->Next;tail->Name=i;tail->RunTime=0;tail->Statu=“Ready”;cout<<“請輸入¨2”<>tail->NeedTime;} if(i==n){ } tail->Next=new Process;tail=tail->Next;tail->Next=head;tail->Name=i;tail->RunTime=0;tail->Statu=“Ready”;cout<<“請輸入¨2”<>tail->NeedTime;tail=head;return tail;void Run(struct Process *tail,int ProcessNum)//時間片輪轉 { while(ProcessNum!=0){ if((tail->RunTime!=tail->NeedTime)) { cout<<“進程”< if(tail->RunTime==tail->NeedTime) { tail->RunTime++; if(tail->Statu==“Ready”){ tail->Statu=“End”; ProcessNum--; } } tail=tail->Next; } else { tail=tail->Next; } } } int main(){ struct Process * runtail;runtail=NULL;int n;int ProcessNum;cout<<“請輸入進程的個數”;cin>>n;ProcessNum=n;runtail=CreateList(n);Run(runtail,ProcessNum);getchar();getchar();} 實驗結果: 電子科技大學計算機學院實驗中心 八、實驗結論、心得體會和改進建議: 實驗結論:成功的采用鏈表的形式,用指針,模仿了時間片輪轉算法,完成了實驗的要求,達到了實驗的目的。 心得體會:通過本次實驗加深了我們對時間輪轉算法的印象,并且鍛煉了我們的動手能力,還溫習了一下C++中一些編程的知識。 改進建議:我覺得時間片算法可能過于簡單了,其實我們可以在時間片算法的基礎上再增加一些功能,比如在時間片算法上增加優先級這個屬性,這樣不僅加大了實驗的難度,還可以讓同學們對優先級調度有一種更直觀,更深刻的了解。 實驗三 一、實驗名稱:主存儲器空間的分配與回收 二、實驗學時:4 三、實驗內容和目的: 實驗內容: 電子科技大學計算機學院實驗中心 分頁式管理方式采用位示圖來表示主存分配情況,實現主存空間的分配和回收。 實驗目的: 一個好的計算機系統不僅要有一個足夠容量的、存取速度高的、穩定可靠的主存儲器,而且要能合理地分配和使用這些存儲空間。 當用戶提出申請存儲器空間時,存儲管理必須根據申請者的要求,按一定的策略分析主存空間的情況,找出足夠的空閑區域分配給申請者。當作業撤離或主動歸還主存資源時,則存儲 管理要收回作業占用的主存空間或歸還部分主存空間。主存的分配和回收的實現雖與主存儲器的管理方式有關的。 通過本實驗幫助學生理解在不同的存儲管理方式下應怎樣實現主存空間的回收和分配。 四、實驗原理: (1)分頁式存儲器把主存分成大小相等的若干塊,作業的信息也按塊的大小分頁,作業裝入主存時可把作業的信息按頁分散存放在主存的空閑塊中,為了說明主存中哪些塊已經被占用,哪些塊是尚未分配的空閑塊,可用一張位示圖來指出。位示圖可由若干存儲單元來構成,其中每一位與一個物理塊對應,用0/1表示對應塊為空閑/已占用。(2)設某系統主存被分成大小相等的64塊,則位示圖可用8*8個字節來構成,另用一單元記錄當前空閑塊數。若已有第0,1,4,5,6,9,11,13,24,31,共10個主存塊被占用了,那么位示圖情況如下: (3)當裝入一個作業時,根據作業對主存的需要量,先查當前空閑塊數是否能滿足作業要求,若不能滿足則輸出分配不成功。若能滿足,則查位示圖,找出為“0”的一些位,置上占用標志“1”,并且從“當前空閑塊數”中減去本次任務占用塊數。然后按找到的計算出對應的塊號: 其計算公式為: 塊號= j*8+i 其中,j表示找到的是第n個字節,i表示對應的是第n位。根據分配給作業的塊號,為作業建立一張頁表,頁表格式: (4)當作業執行結束,歸還主存時,根據該作業的頁表可以知道應歸還的塊號。 電子科技大學計算機學院實驗中心 由塊號可計算出在位示圖中的對應位置,把對應位的占用標志清成“0”,表示對應的塊已成為空閑塊。歸還的塊數加入到當前空閑塊數中。由塊號計算在位示圖中的位置的公式如下: 字節號 j=[塊號/8]([ ]表示取整) 位數 i={塊號/8}({ }表示取余) (5)設計實現主存分配和回收的程序。假定位示圖的初始狀態如(2)所述,現 有一信息量為N頁的作業要裝入,運行你所設計的分配程序,為作業分配主存且建立頁表(格式如(3)所述)。 五、實驗器材(設備、元器件): 一臺裝有VS2010的電腦,操作系統為WIN7.六、實驗步驟: (1)先創建一個8*8的數組,用來保存內存的信息。并初始化好值,用1來表示已經分配,用0來表示還沒有分配。 (2)創建一個Sum函數,來對內存中沒有分配的內存個數進行統計,并返回一個int類型的數值,來表示沒有分配的內存的大小、(3)創建一個分配內存的函數,先判斷需求的內存的大小是否小于內存空閑的大小。如果能夠滿足要求,則將相應的內存空間修改為1,表示已經分配。(4)創建一個打印內存頁表的函數,根據內存的實際情況,如果為1,則打印輸出,最后在屏幕上打印出所有的空閑頁表。 (5)創建主函數,并對相應的函數進行調用,便可成功的模仿內存的調度。 七、實驗數據及結果分析: 具體的代碼如下: #include void Print(int Table[8][8])//顯示內存 } int Sum(int Table[8][8])//計算內存的剩余量 { int n=0;for(int j=0;j<8;j++) { } { cout<<“分配內存后最新的內存情況如下表”< cout<<“ ”<<0<<“ ”<<1<<“ ”<<2<<“ ”<<3<<“ ”<<4<<“ ”<<5<<“ ”<<6<<“ ”<<7<<“n”; for(int j=0;j<8;j++) cout< for(int k=0;k<8;k++) { cout<<“ ”< } cout<<“n”; { 電子科技大學計算機學院實驗中心 } for(int k=0;k<8;k++) { if(Table[j][k]==0) { n++; } } } return n;void Manage(int Table [8][8],int Need)//分配內存 { } void YeBiao(int Table [8][8])//打印空閑頁表 { cout<<“分配后空閑內存的頁表”< ”<<“塊號”< { for(int k=0;k<8;k++) { if(Table [j][k]==0) { h=8*j+k; cout< ”< for(int j=0;j<8;j++) { } for(int k=0;k<8;k++) { if(Table [j][k]==0&&Need!=0) { } Table [j][k]=1; Need--; } } } } } } int main(){ cout<<“請輸入你要分配的塊數”;cin>>Need;while(Need>Va){ } Manage(Table,Need);Print(Table);cout<<“對不起沒有足夠內存,請重新輸入n”;cin>>Need;int Table[8][8];int Va,Need;for(int i=0;i<8;i++)//初始化頁表 { } Table[0][0]=1;Table[0][1]=1;Table[0][4]=1;Table[0][5]=1;Table[0][6]=1;Table[1][1]=1;Table[1][3]=1;Table[1][5]=1;Table[3][0]=1;Table[3][7]=1;Print(Table);Va=Sum(Table);cout<<“n”<<“現在有”< 電子科技大學計算機學院實驗中心 YeBiao(Table); } getchar();getchar();(1)若申請的內存數過大。 (2)申請的內存為45: 八、實驗結論、心得體會和改進建議: 實驗結論:達到了實驗的要求與目的,完成了對內存分配的模擬。 心得體會:通過本次實驗,我加深了采用頁表的方式來管理內存的印象,鍛煉了自己C++的編程能力,和獨立解決問題的能力。 改進建議:實驗中并沒有要求對內存空間清理,刪除的功能,我希望老師能加上對內存緊湊,清理,刪除這些功能的模擬,這樣可以使我們所學的知識更有用武之地。 電子科技大學計算機學院實驗中心 實驗四 一、實驗名稱: 讀者寫者問題 二、實驗學時:4 三、實驗內容和目的: 實驗內容: 可用于解決多個進程共享一個數據區(文件、內存區、一組寄存器等),其中若干讀進程只能讀數據,若干寫進程只能寫數據等實際問題 讀者和寫者應滿足的條件:(1)允許多個讀者可以同時讀文件 (2)不允許多個寫者同時寫文件,只能互斥寫文件(3)當寫進程在寫時不能讀 (4)讀者優先: 指一旦有讀者正在讀數據,允許多個讀者同時進入讀數據,只有當全部讀者退出,才允許寫者進入寫數據。 (5)寫者優先:指只要有一個寫者申請寫數據,則不再允許新的讀者進入讀數據 實驗目的: 通過本實驗對讀者寫者的模擬,讓我們對操作系統中讀者寫著問題的解決有一個加深的影響,并學會使用一些模擬簡單的信號量的方法,來解決一些比較經典的讀者寫著的問題。 四、實驗原理: (1)為了模擬讀者寫著的問題,因為自己的C++技術不夠深厚,于是用Java中的線程來進行模擬、采用輸入輸出流來對文本文件Test.txt進行操作。(2)要實現寫著互斥的寫文件,這里只需要將線程中的Run方法定義為synchronized,就可以實現寫著互斥的寫文件、(3)引入一個couter類,并對counter類中的成員進行維護,若有讀者讀數據,則對counter內的reader++,寫者同理。 (4)讀者寫著不同的優先級,可以通過依賴counter類來實現。在進行文件讀寫操作時,先判斷是否有讀者/寫者。 五、實驗器材(設備、元器件): 一臺裝有eclipse,和Win7的個人PC。 六、實驗步驟: 電子科技大學計算機學院實驗中心(1)定義讀者,寫者類并繼承Thread類,在其中的Run方法中調用輸入輸出流來,讀寫文件 (2)創建counter類,來對讀者,寫者進行計數。 (3)在主函數中創建讀者寫者,并調用相應的Run方法,并觀察實驗的結果。 七、實驗數據及結果分析: 實驗的具體代碼: import java.util.Scanner; public class ReadAndWrite { public static void main(String []arg){ Scanner in= new Scanner(System.in);System.out.println(“請選擇模擬的情況:1為讀者優先。2為寫者優先”);int Situation;Situation = in.nextInt();if(Situation==2)//寫者優先 { Writer w1=new Writer(1);w1.start();Reader r2=new Reader(2);r2.start();Writer w2=new Writer(2);w2.start(); } else//讀者優先 { Reader1 r1=new Reader1(1);r1.start();Reader1 r2=new Reader1(2);r2.start();Writer1 w2=new Writer1(2);w2.start(); } } } class Counter { static int WriterCounter=0;static int ReaderCounter=0;} class Writer extends Thread//寫者優先 { int WriteNum;Writer(int WriteNum){ this.WriteNum=WriteNum;} synchronized public void run(){ Counter.WriterCounter++; System.out.println(“now Writer”+“ ”+WriteNum+“ ”+“is Writing”); for(int i=0;i<10;i++){ System.out.println(“********************************”); } Counter.WriterCounter--;} } class Writer1 extends Thread { int WriteNum;Writer1(int WriteNum){ this.WriteNum=WriteNum;} synchronized public void run(){ if(Counter.ReaderCounter==0) { Counter.WriterCounter++; System.out.println(“now Writer”+“ ”+WriteNum+“ ”+“is Writing”); for(int i=0;i<10;i++){ System.out.println(“********************************”); } 電子科技大學計算機學院實驗中心 Counter.WriterCounter--; } else { System.out.println(“Now File is Reading,Writer can't Write”); try{ sleep(1000); }catch(Exception ex) { ex.printStackTrace(); } System.out.println(“********************************”); System.out.println(“Writer is Writing”); } } } class Reader extends Thread { int ReadNum;Reader(int ReadNum){ this.ReadNum=ReadNum;} public void run(){ if(Counter.WriterCounter==0) { Counter.ReaderCounter++; System.out.println(“now Reader”+“ ”+ReadNum+“ ”+“is Reading”); for(int i=0;i<10;i++){ System.out.println(“********************************”); } Counter.ReaderCounter--; } else { System.out.println(“now File is Writing,Reader can't Read”); try{ sleep(1000); }catch(Exception ex) { ex.printStackTrace(); } System.out.println(“********************************”); System.out.println(“Reader is Reading”); } } } class Reader1 extends Thread//讀者優先 { int ReadNum;Reader1(int ReadNum){ this.ReadNum=ReadNum;} public void run(){ Counter.ReaderCounter++; System.out.println(“now Reader”+“ ”+ReadNum+“ ”+“is Reading”); for(int i=0;i<10;i++){ System.out.println(“********************************”); } Counter.ReaderCounter--; } } 實驗的結果:(1)讀者優先: 電子科技大學計算機學院實驗中心(2)寫者優先: 八、實驗結論、心得體會和改進建議: 實驗結論:基本完成了實驗的要求,實現了對經典的讀者寫著問題的解決。心得體會:通過本次實驗,加深了我對讀者寫著問題的理解,學會了用軟件模擬的辦法來實現一些簡單的信號量對讀者寫者的控制,并且鍛煉了自己Java編程的能力,和獨立解決問題的能力 改進建議:實際上,對于讀者寫者的問題,我們有多種解決辦法,在這里我們只是模擬了一下軟件編程的方法,還有一些方法,比如信號量,中斷屏蔽等方法,還沒有模擬,所以希望在以后的實驗中可以增加一些對這些方法的模擬,以加深我們對讀者寫者問題的理解。 進程調度算法模擬 專業:XXXXX 學號:XXXXX 姓名:XXX 實驗日期:20XX年XX月XX日 一、實驗目的 通過對進程調度算法的模擬加深對進程概念和進程調度算法的理解。 二、實驗要求 編寫程序實現對5個進程的調度模擬,要求至少采用兩種不同的調度算法分別進行模擬調度。 三、實驗方法內容 1.算法設計思路 將每個進程抽象成一個控制塊PCB,PCB用一個結構體描述。 構建一個進程調度類。將進程調度的各種算法分裝在一個類中。類中存在三個容器,一個保存正在或未進入就緒隊列的進程,一個保存就緒的進程,另一個保存已完成的進程。還有一個PCB實例。主要保存正在運行的進程。類中其他方法都是圍繞這三個容器可以這個運行中的PCB展開。 主要用到的技術是STL中的vector以維護和保存進程容器、就緒容器、完成容器。 當程序啟動時,用戶可以選擇不同的調度算法。然后用戶從控制臺輸入各個進程的信息,這些信息保存到進程容器中。進程信息輸入完畢后,就開始了進程調度,每調度一次判斷就緒隊列是否為空,若為空則系統時間加一個時間片。判斷進程容器中是否有新的進程可以加入就緒隊列。2.算法流程圖 主程序的框架: 開始void FCFS();//先來先服務void SJF();//最短進程優先調度void RR();//簡單時間片輪轉void PD();//最高優先數優先void PCBInput();//輸入進程信息選擇調度算法輸入進程信息將輸入容器中以滿足進入條件的進程調入就緒隊列void ProcessQueueProcess();//查看當前時間下,有無進程加入。若有則把該進程調入就緒隊列按照選擇的算法開始選擇就緒隊列的進程開始執行void ProcessSelect();//若當前就緒隊列不為空則根據選擇的調度算法開始調度,否則,系統時間加一個時間片.以等待新的進程到判斷就緒容器和輸入容器是否為空!processScheduler.m_WaitQueue.empty()||!processScheduler.m_ProcessQueue.empt()Y打印各進程信息進行統計計算周轉時間等結束void PCBDisplay();//打印當前狀況下。就緒隊列、完成隊列、運行中的進程信息void SchedulerStatistics();//調度統計,計算周轉時間等進程調度過程: 開始為空判斷就緒隊列是否為空if(m_WaitQueue.empty())非空讓系統等待一個時間片TimePast()根據設定的調度算法從就緒隊列中調入一個進程并執行(此時進程從就緒隊列中刪除,賦值到表示運行中的成員變量中)void FCFS();//先來先服務void SJF();//最短進程優先調度void RR();//簡單時間片輪轉void PD();//最高優先數優先進程運行一個時間片N是否達到該進程停止運行的條件Y選入的進程狀態是否為“完成”如進程已完成,或者分得的時間片個數已到ProcessRun()Yvector m_WaitQueue;//進程就緒隊列進程未完成,將進程優先數減一,并放回到就緒隊列中設置進程完成時間,將該進程放入完成隊列vector m_FinishQueue;//完成隊列結束 3.算法中用到的數據結構 struct fcfs{ //先來先服務算法從這里開始 char name[10]; float arrivetime; float servicetime; float starttime; float finishtime; float zztime; float dqzztime; }; //定義一個結構體,里面包含的有一個進程相關的信息 4.主要的常量變量 vector m_ProcessQueue;//進程輸入隊列 vector m_WaitQueue;//進程就緒隊列 vector m_FinishQueue;//完成隊列 vector ::iterator m_iter;//迭代器 PCB m_runProcess;//運行中的進程 int m_ProcessCount;//進程數 float m_RunTime;//運行時間 int m_tagIsRun;//是否在運行標志。表示正在運行,表示沒有 float m_TimeSlice;//時間片大小 int m_TimeSliceCount;//指時間片輪轉中一次分到的時間片個數 char m_SchedulerAlgorithm;//調度算法 5.主要模塊 void PCBInput();//輸入進程信息 void PCBSort();//對進程控制塊按照優先級排序(采用冒泡排序)void ProcessSelect();//若當前就緒隊列不為空則根據選擇的調度算法開始調度。否則,系統時間void PCBDisplay();//打印當前狀況下。就緒隊列、完成隊列、運行中的進程信息 void ProcessRun();//進程運行一次。運行時間加個時間片。并判斷進程是否達到完成條件。若是則void ProcessQueueProcess();//查看當前時間下,有無進程加入。若有則把該進程調入就緒隊列 void ProcessDispatch();//進程分派,進程執行完成后決定進程該進入哪個隊列(就緒、完成)void TimePast(){ m_RunTime +=m_TimeSlice;ProcessQueueProcess();}//當前系統時間加個時間void SchedulerStatistics();//調度統計,計算周轉時間等 void FCFS();//先來先服務 void SJF();//最短進程優先調度 void RR();//簡單時間片輪轉 void PD();//最高優先數優先 加.以等待新的進程到來 ProcessStatus='f'.否則為'w';片,并檢查是否有新的進程加入 四、實驗代碼 #include using namespace std; struct fcfs{ //先來先服務算法從這里開始 char name[10]; float arrivetime; float servicetime; float starttime; float finishtime; float zztime; float dqzztime; }; //定義一個結構體,里面包含的有一個進程相關的信息 fcfs a[100]; void input(fcfs *p,int N) { int i; cout< printf(“ 請您輸入進程的名字 到達時間 服務時間:(例如: a 0 100)nn”); for(i=0;i<=N-1;i++) { printf(“ 請您輸入進程%d的信息:t”,i+1); scanf(“ttt%s%f%f”,&p[i].name,&p[i].arrivetime,&p[i].servicetime); } } void Print(fcfs *p,float arrivetime,float servicetime,float starttime,float finishtime,float zztime,float dqzztime,int N) { int k; printf(“nn調用先來先服務算法以后進程運行的順序是: ”); printf(“%s”,p[0].name); for(k=1;k { printf(“-->%s”,p[k].name); } cout< printf(“n 具體進程調度信息:n”); printf(“t進程名 到達時間 服務時間 開始時間 結束時間 周轉時間 帶權周轉時間n”); for(k=0;k<=N-1;k++) { printf(“t%st%-.2ft %-.2ft %-.2ft %-.2ft %-.2ft %-.2fn”,p[k].name,p[k].arrivetime,p[k].servicetime,p[k].starttime,p[k].finishtime,p[k].zztime,p[k].dqzztime); } getchar(); //此處必須要有這個函數,否則就看不到顯示器上面的輸出,可以看到的結果只是一閃而過的一個框剪 } void sort(fcfs *p,int N)//排序 { for(int i=0;i<=N-1;i++) for(int j=0;j<=i;j++) if(p[i].arrivetime { fcfs temp; temp=p[i]; p[i]=p[j]; p[j]=temp; } } void deal(fcfs *p, float arrivetime,float servicetime,float starttime,float finishtime,float &zztime,float &dqzztime,int N) //運行階段 { int k; for(k=0;k<=N-1;k++) { if(k==0) { p[k].starttime=p[k].arrivetime; p[k].finishtime=p[k].arrivetime+p[k].servicetime;} else { p[k].starttime=p[k-1].finishtime; p[k].finishtime=p[k-1].finishtime+p[k].servicetime;} } for(k=0;k<=N-1;k++) { p[k].zztime=p[k].finishtime-p[k].arrivetime; p[k].dqzztime=p[k].zztime/p[k].servicetime; } } void FCFS(fcfs *p,int N) { float arrivetime=0,servicetime=0,starttime=0,finishtime=0,zztime=0,dqzztime=0; sort(p,N); deal(p,arrivetime,servicetime,starttime,finishtime,zztime,dqzztime,N); Print(p,arrivetime,servicetime,starttime,finishtime,zztime,dqzztime,N); getchar(); } //先來先服務算法到此結束 struct sjf{//最短進程優先調度算法從這里開始 char name[10];float arrivetime;//到達時間 float servicetime;//運行時間 float starttime; //開始時間 float finishtime; //完成時間 };sjf a1[100]; void input(sjf *p,int N1)//進程信息輸入 { int i;cout< printf(“ 請您輸入進程的名字 到達時間 服務時間:(例如: a 0 100)n”); for(i=0;i<=N1-1;i++){ printf(“ 請您輸入進程%d的信息:t”,i+1); scanf(“ttt%s%f%f”,&p[i].name,&p[i].arrivetime,&p[i].servicetime);} } void Print(sjf *p,float arrivetime,float servicetime,float starttime,float finishtime,int N1)//最終結果輸出 { int k; printf(“nt調用最短進程優先調度算法以后進程的調度順序為:”); printf(“%s”,p[0].name); for(k=1;k {printf(“-->%s”,p[k].name);} cout< printf(“n給個進程具體調度信息如下:n”); printf(“nt進程名t到達時間t運行時間t開始時間t完成時間n”); for(k=0;k<=N1-1;k++) { printf(“ t%st %-.2ftt %-.2ftt %-.2ftt %-.2ftn”,p[k].name,p[k].arrivetime,p[k].servicetime,p[k].starttime,p[k].finishtime); } getchar(); } void sort(sjf *p,int N1)//排序 { for(int i=0;i<=N1-1;i++) for(int j=0;j<=i;j++) if(p[i].arrivetime { sjf temp; temp=p[i]; p[i]=p[j]; p[j]=temp; } } void deal(sjf *p, float arrivetime,float servicetime,float starttime,float finishtime,int N1)//運行階段 { int k; for(k=0;k<=N1-1;k++) { if(k==0) { p[k].starttime=p[k].arrivetime; p[k].finishtime=p[k].arrivetime+float(p[k].servicetime)/60;} else { p[k].starttime=p[k-1].finishtime; p[k].finishtime=p[k-1].finishtime+float(p[k].servicetime)/60;} } } void sjff(sjf *p,int N1){ float arrivetime=0,servicetime=0,starttime=0,finishtime=0; sort(p,N1); for(int m=0;m {if(m==0) p[m].finishtime=p[m].arrivetime+float(p[m].servicetime)/60; else p[m].finishtime=p[m-1].finishtime+float(p[m].servicetime)/60; int i=0; for(int n=m+1;n<=N1-1;n++) { if(p[n].arrivetime<=p[m].finishtime) i++; } float min=p[m+1].servicetime; int next=m+1; for(int k=m+1;k { if(p[k+1].servicetime {min=p[k+1].servicetime; next=k+1;} } sjf temp; temp=p[m+1]; p[m+1]=p[next]; p[next]=temp; } deal(p,arrivetime,servicetime,starttime,finishtime,N1); Print(p,arrivetime,servicetime,starttime,finishtime,N1); getchar();}//最短進程優先調度算法到這里結束 char menu()//用來輸出相關信息的函數 { char cse1; while(1) { system(“cls”); fflush(stdin); cout< cout< cout<<“t”<<“|| <<<<<<<<<<<<歡<<<<<<<<<<< >>>>>>>>>>>>迎>>>>>>>>>>> ||”< cout<<“t”<<“|| ||”< cout<<“t”<<“||”<<“t 進程調度算法模擬”<<“tt”<<“||”< cout<<“t”<<“|| ||”< cout<<“t”<<“||”<<“tt 1.先來先服務調度算法 ”<<“tt”<<“||”< cout<<“t”<<“|| ||”< cout<<“t”<<“||”<<“tt 2.最短進程優先調度算法”<<“tt”<<“||”< cout<<“t”<<“|| ||”< cout<<“t”<<“|| <<<<<<<<<<<<<<<<<<<<<<<<<您>>>>>>>>>>>>>>>>>>>>>>>>> ||”< cout< cout< cout<<“tt 請輸入您的選擇(1/2):”; cse1=getchar(); if(cse1<'1'||cse1>'2') cout<<“你的輸入有錯!”< else break; } return cse1;} int main(int argc, char *argv[]){ while(1) { switch(menu()) { case '1': int N; cout< cout< printf(“tt<<---!!@@@先來先服務調度算法@@@!!--->>n”); cout< printf(“輸入進程數目:”); scanf(“%d”,&N); input(a,N); FCFS(a,N); case '2': int N1; cout< cout< printf(“tt<<---!!@@@最短進程優先調度算法@@@!!--->>n”); cout< printf(“輸入進程數目: ”); scanf(“%d”,&N1); input(a1,N1); sjf *b=a1; sjf *c=a1; sjff(b,N1); getchar(); } } system(“PAUSE”); return EXIT_SUCCESS;} 五、實驗結果 1.執行結果 2.結果分析 先來先服務調度算法就是根據進程達到的時間為依據,哪一個進程先來那么該進程就會先執行;最短進程優先調度算法則是以每個進程執行所需時間長短為依據,某一個進程執行所需花的時間要短些那么該進程就先執行。以上就是本次進程調度實驗的依據。 六、實驗總結 通過本次實驗了解到算法很重要,又更加明白算法本身可以節約時間,而且不同的函數之間在調用的時候要注意很多的問題。 實 驗 報 告 學生姓名: 學 號: 指導教師: 一、實驗室名稱: 二、實驗項目名稱:進程調度算法的設計 三、實驗原理: 短作業(進程)優先調度算法:短作業調度算法是從后備隊列中選擇一個或者若干個估計運行時間最短的作業,將他們調入內存運行。而短進程優先調度算法則是從就緒隊列中選出一個估計運行時間最短的進程,將處理機分配給它,使它立即執行并一直執行到完成,或者發生某事件而被阻塞放棄處理機時再重新調度。 時間片輪轉法:系統將所有的就緒進程按先來先服務的原則排成一個隊列,每次調度時,把CPU分配給隊首進程,并令其執行一個時間片。當執行的時間片用完時,由一個計時器發出時鐘中斷請求,調度程序便據此信號來停止該進程的執行,并將它送往就緒隊列的隊尾;然后,再把處理機分配給就緒隊列中的新的隊首進程,同時也讓它執行一個時間片。這樣就可以保證就緒隊列中的所有進程在一個給定的時間內均能獲得一時間片的處理機執行時間。 四、實驗目的: 通過對進程調度算法的設計,深入理解進程調度的原理 五、實驗內容: 1.編寫程序實現SJ(P)F算法 2.編寫程序實現RR算法 六、實驗器材(設備、元器件): 裝有VC++6.0的PC機一臺 七、實驗步驟: 1.打開VC,設計編寫程序的源代碼 2.編譯運行程序的源代碼 3.分析檢驗程序的結果是否正確 4.總結實驗結果及結論 短進程優先調度源代碼: #include “stdio.h” struct sjf{ char name[10];float arrivetime;float servicetime;float starttime;float finishtime;float zztime;float dqzztime;};sjf a[100];void input(sjf *p,int N){ int i;printf(“intput the process's name & arrivetime & servicetime:nfor exmple: a 0 100n”);for(i=0;i<=N-1;i++){ printf(“input the %dth process's information:n”,i+1);scanf(“%s%f%f”,&p[i].name,&p[i].arrivetime,&p[i].servicetime);} } void Print(sjf *p,float arrivetime,float servicetime,float starttime,float finishtime,float zztime,float dqzztime,int N){int k; printf(“run order:”); printf(“%s”,p[0].name);for(k=1;k printf(“nthe process's information:n”); printf(“nnametarrivetservicetstarttfinishtzztdqzzn”); for(k=0;k<=N-1;k++){ printf(“%st%-.2ft%-.2ft%-.2ft%-.2ft%-.2ft%-.2ftn”,p[k].name,p[k].arrivetime,p[k].servicetime,p[k].starttime,p[k].finishtime,p[k].zztime,p[k].dqzztime);} } //排序 void sort(sjf *p,int N){ for(int i=0;i<=N-1;i++) for(int j=0;j<=i;j++) if(p[i].arrivetime { sjf temp; temp=p[i]; p[i]=p[j]; p[j]=temp; } } //運行階段 void deal(sjf *p, float arrivetime,float servicetime,float starttime,float finishtime,float &zztime,float &dqzztime,int N){ int k; for(k=0;k<=N-1;k++) { if(k==0) { p[k].starttime=p[k].arrivetime; p[k].finishtime=p[k].arrivetime+p[k].servicetime;} else { p[k].starttime=p[k-1].finishtime; p[k].finishtime=p[k-1].finishtime+p[k].servicetime;} } for(k=0;k<=N-1;k++) { p[k].zztime=p[k].finishtime-p[k].arrivetime; p[k].dqzztime=p[k].zztime/p[k].servicetime; } } void sjff(sjf *p,int N){float arrivetime=0,servicetime=0,starttime=0,finishtime=0,zztime=0,dqzztime=0;//對結構進行初始化 sort(p,N); for(int m=0;m {if(m==0) p[m].finishtime=p[m].arrivetime+p[m].servicetime; else p[m].finishtime=p[m-1].finishtime+p[m].servicetime; int i=0; for(int n=m+1;n<=N-1;n++) {if(p[n].arrivetime<=p[m].finishtime)//判斷內存中每次完成之后有多少到達的進程 i++; } float min=p[m+1].servicetime; int next=m+1;//m+1=n for(int k=m+1;k { if(p[k+1].servicetime {min=p[k+1].servicetime; next=k+1;} } sjf temp; temp=p[m+1]; p[m+1]=p[next]; p[next]=temp; } deal(p,arrivetime,servicetime,starttime,finishtime,zztime,dqzztime,N); Print(p,arrivetime,servicetime,starttime,finishtime,zztime,dqzztime,N);} void main(){ int N; printf(“------短作業優先調度算法------n”); printf(“input the process's number:n”); scanf(“%d”,&N); input(a,N); sjf *b=a; sjf *c=a; sjff(b,N);} 時間片輪轉法源代碼: #include //物理頁數 #define printf(“|---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---|n”)typedef struct PCB { int ID;int ReachTime;int TotalTime;}PCB;//進程號,到達時間和服務時間 typedef struct NOTE //備份 { Myprintf int ID;int TotalTime;}NOTE; PCB A[M];//5個進程 PCB a[M];NOTE temp;int queue[50];//記錄調度的進程 int K=0;//調度進程數組的標識 void INIT()//初始化 { int i;for(i=0;i A[i].ID=-1;} } int GetNum()//計算進程數 { int i,j=0;for(i=0;i if(A[i].ID!=-1) { j++; } } return j;} int GetReach(int time)//找出到達進程號 { int i;for(i=0;i if(a[i].ReachTime<=time) { a[i].ReachTime=100; return i; } } return-1;} int GetInsert()//找出插入位置 { int i;for(i=0;i if(A[i].ID==-1) return i;} return-1;} void Forward(int num)//前移 { int i;for(i=0;i A[i].ID=A[i+1].ID; A[i].TotalTime=A[i+1].TotalTime;} A[num-1].ID=-1;} void Process()//執行進程 { queue[K]=A[0].ID;K++;A[0].TotalTime--;temp.ID=A[0].ID;temp.TotalTime=A[0].TotalTime;} void main(){ int i;int time;int t=0;int reach;int insert;int num;printf(“RR算法nn”);INIT();for(i=0;i printf(“請輸入進程ID:”); scanf(“%d”,&a[i].ID); printf(“請輸入到達時間:”); scanf(“%d”,&a[i].ReachTime); printf(“請輸入服務時間:”); scanf(“%d”,&a[i].TotalTime); } for(i=0;i { insert=GetInsert(); A[insert].ID=a[reach].ID; A[insert].TotalTime=a[reach].TotalTime; num=GetNum(); if(num==1) continue;//進程數為1 else { //進程數不為1 Process(); Forward(num); if(temp.TotalTime!=0) { A[num-1].ID=temp.ID; A[num-1].TotalTime=temp.TotalTime; } } } else//沒有進程到達 { num=GetNum(); if(num==1) {//進程數為1 Process(); if(temp.TotalTime==0) { A[0].ID=-1; } } else if(num==0) } continue;//進程數為0 else { Process(); Forward(num); if(temp.TotalTime!=0) { A[num-1].ID=temp.ID; A[num-1].TotalTime=temp.TotalTime; } } } } printf(“n”);printf(“調度順序為:n”);Myprintf;for(i=0;i<50;i++){ if(queue[i]!=-1) printf(“|%2d ”,queue[i]);} printf(“|n”);Myprintf;printf(“n”); 八、實驗數據及結果分析: 短作業優先調度算法的實驗結果: 時間片輪轉調度算法結果: 九、實驗結論: 本次實驗成功的完成了短作業優先調度算法和輪轉時間片調度算法的模擬,通過本次實驗我們了解到短作業優先調度算法不利于長作業的處理,因為長作業將長期得不到處理,而輪轉時間片調度算法則解決了這一問題。短長作業均能在每一個周期內分得一個時間片處理自己的任務。 十、總結及心得體會: 通過本次實驗對短作業優先調度算法和時間片輪轉調度算法有了更深入的理解,同時,對程序算法能力有了進一步的提高,同時對模塊化編程有了更深入得理解,代碼的模塊化會使程序的代碼復用率提高,提高編程的效率。 十一、對本實驗過程及方法、手段的改進建議: 本次實驗的時間片輪轉調度算法由于教材版本不一樣有兩種結果,本次實驗本人采取的新教材的版本,新版本的難度較老教材要大很多,實驗時候可以根據具體情況選擇一個適合自己的來做。 報告評分: 指導教師簽字: 文檔為doc格式第二篇:操作系統進程調度算法模擬實驗報告
第三篇:短作業優先調度和時間片輪轉調度算法
聲明:本文內容由互聯網用戶自發貢獻自行上傳,本網站不擁有所有權,未作人工編輯處理,也不承擔相關法律責任。如果您發現有涉嫌版權的內容,歡迎發送郵件至:645879355@qq.com 進行舉報,并提供相關證據,工作人員會在5個工作日內聯系你,一經查實,本站將立刻刪除涉嫌侵權內容。