操作系統實驗-設計一個時間片輪轉法實現處理器調度的程序

實驗三
一、實驗題目
設計一個按時間片輪轉法實現處理器調度的程序。
二、實驗內容
(1) 假定系統有五個進程,每一個進程用一個進程控制塊PCB來代表。進程控制塊的格式爲:
進程名
指針
要求運行時間
已運行時間
狀態
其中,進程名——作爲進程的標識,假設五個進程的進程名分別爲Q1,Q2,Q3,Q4,Q5。
指針——進程按順序排成循環隊列,用指針指出下一個進程的進程控制塊的首地址,最後一個進程的指針指出第一個進程的進程控制塊首地址。
要求運行時間——假設進程需要運行的單位時間數。
已運行時間——假設進程已經運行的單位時間數,初始值爲“0”。
狀態——有兩種狀態,“就緒”和“結束”,初始狀態都爲“就緒”,用“R”表示。當一個進程運行結束後,它的狀態爲“結束”,用“E”表示。
(2) 每次運行所設計的處理器調度程序前,爲每個進程任意確定它的“要求運行時間”。
(3) 把五個進程按順序排成循環隊列,用指針指出隊列連接情況。另用一標誌單元記錄輪到運行的進程。例如,當前輪到P2執行,則有:
標誌單元
在這裏插入圖片描述
(4) 處理器調度總是選擇標誌單元指示的進程運行。由於本實驗是模擬處理器調度的功能,所以,對被選中的進程並不實際的啓動運行,而是執行:
已運行時間+1
來模擬進程的一次運行,表示進程已經運行過一個單位的時間。
請同學注意:在實際的系統中,當一個進程被選中運行時,必須置上該進程可以運行的時間片值,以及恢復進程的現場,讓它佔有處理器運行,直到出現等待事件或運行滿一個時間片。在這時省去了這些工作,僅用“已運行時間+1”來表示進程已經運行滿一個時間片。
(5) 進程運行一次後,應把該進程的進程控制塊中的指針值送到標誌單元,以指示下一個輪到運行的進程。同時,應判斷該進程的要求運行時間與已運行時間,若該進程的要求運行時間已運行時間,則表示它尚未執行結束,應待到下一輪時再運行。若該進程的要求運行時間=已運行時間,則表示它已經執行結束,應指導它的狀態修改成“結束”(E)且退出隊列。此時,應把該進程的進程控制塊中的指針值送到前面一個進程的指針位置。
(6) 若“就緒”狀態的進程隊列不爲空,則重複上面的(4)和(5)的步驟,直到所有的進程都成爲“結束”狀態。
(7) 在所設計的程序中應有顯示或打印語句,能顯示或打印每次選中進程的進程名以及運行一次後進程隊列的變化。
(8) 爲五個進程任意確定一組“要求運行時間”,啓動所設計的處理器調度程序,顯示或打印逐次被選中的進程名以及進程控制塊的動態變化過程。
三、實驗過程
1、實驗原理
在這裏插入圖片描述
2、數據結構
typedef struct PNode //PCB
{ struct PNode *next; //定義指向下一個節點的指針
char name[10]; //定義進程名,並分配空間
int All_time; //定義總運行時間
int Runed_Time; //定義已運行時間
char state; //定義進程狀態Ready/End
}
*Proc; //指向該PCB的指針
int ProcNum; //總進程數
3、算法設計
void SJP_Simulator(Proc &H)
{
cout << endl << “-------------START-----------------\n”;
int flag = ProcNum; //記錄剩餘進程數
int round = 0; //記錄輪轉數
Proc p = H->next;
while (p->All_time>p->Runed_Time)
{
round++;
cout << endl << “Round” << round << “–正在運行” << p->name << “進程” << endl;
p->Runed_Time++; //更改正在運行的進程的已運行的時間
Displnfo(H); //輸出此時爲就緒狀態的進程 的信息
if (p->All_time = = p->Runed_Time)
{
//判斷該進程是否結束
p->state = ‘E’;
flag–;
cout << p->name << “進程已運行結束,進程被刪除!\n”;
}
p = p->next;
while (flag && p->All_time == p->Runed_Time)
p = p->next; //跳過先前已結束的進程
}
cout << endl << “-------------------END-----------------\n”;
}
四、實驗結果
在這裏插入圖片描述
五、體會與收穫
時間片輪轉算法中,系統將所有的就緒程序按先來先服務的原則排成一個隊列,每次調度時,把CPU分配給隊首進程,並令其執行一個時間片(一個較小的時間單元)。輪轉法是一種剝奪式調度,當執行的時間片用完時,調度程序停止該進程的執行,並將它送往就緒隊列的末尾;然後,再把處理機分配給就緒隊列中新的隊首進程,同時也讓它執行一個時間片,就這樣一次又一次地執行,一次又一次地等待,直到該進程的任務完成。時間片輪轉調度算法特別適合於分時系統中使用。該算法的難度和關鍵在於選擇合理的時間片。如果時間片過長,時間片輪轉法就變成了先來先服務調度算法,如果時間片過小,則系統會花費大部分時間用於上下文切換。

六、源代碼
#include
#include
using namespace std;
typedef struct PNode ///PCB
{
struct PNode *next; ///定義指向下一個節點的指針
char name[10]; ///定義進程名,並分配空間
int All_time; ///定義總運行時間
int Runed_Time; ///定義已運行時間
char state; ///定義進程狀態Ready/End
}
*Proc; ///指向該PCB的指針
int ProcNum; ///總進程數
///初始化就緒隊列
void lnitPCB(Proc &H)
{
cout << “請輸入總進程個數:”;
cin >> ProcNum; ///進程總個數
int Num = ProcNum;
H = (Proc)malloc(sizeof(PNode)); ///建立頭結點
H->next = NULL;
Proc p = H; ///定義一個指針
cout << “總進程個數爲” << ProcNum << “個,請依次輸入相應信息”<<endl;
cout << endl;
while (Num–)
{
p = p->next = (Proc)malloc(sizeof(PNode));
cout << “進程名,總運行時間,已運行時間:”;
cin >> p->name >> p->All_time >> p->Runed_Time;
p->state = ‘R’;
p->next = NULL;
}
p->next = H->next;
}
///輸入運行中的進程信息
void Displnfo(Proc H)
{
Proc p = H->next;
do
{
if (p->state != ‘E’) ///如果該進程的狀態不是End 的話
{
cout << “進程名:” << p->name << “\t總運行時間:” << p->All_time << “\t已運行時間” << p->Runed_Time << “\t狀態:” << p->state << endl;
p = p->next;
}
else p = p->next;
} while (p != H->next); ///整個進程鏈條始終完整,只是狀態位有差異
}
///時間片輪轉法
void SJP_Simulator(Proc &H)
{
cout << endl << “-------------START-----------------\n”;
int flag = ProcNum; ///記錄剩餘進程數
int round = 0; ///記錄輪轉數
Proc p = H->next;
while (p->All_time>p->Runed_Time)
{
round++;
cout << endl << “Round” << round << “–正在運行” << p->name << “進程” << endl;
p->Runed_Time++; ///更改正在運行的進程的已運行的時間
Displnfo(H); ///輸出此時爲就緒狀態的進程 的信息
if (p->All_time = = p->Runed_Time)
{
//判斷該進程是否結束
p->state = ‘E’;
flag–;
cout << p->name << “進程已運行結束,進程被刪除!\n”;
}
p = p->next;
while (flag && p->All_time == p->Runed_Time)
p = p->next; ///跳過先前已結束的進程
}
cout << endl << “-------------------END-----------------\n”;
}
int main()
{
Proc H;
lnitPCB(H); ///數據初始化
Displnfo(H); ///輸出此刻的進程狀態
SJP_Simulator(H);///時間片輪轉法
system(“pause”);
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章