1. 程式人生 > >處理機排程演算法C語言實現(註釋得當!!)

處理機排程演算法C語言實現(註釋得當!!)

/*
    created by herbert on 10 Nov
 */

#include <iostream>
#include <queue>
#include <algorithm>
#include <cstdio>
#include <iomanip>
using namespace std;

//程序有三種狀態,這裡增加一種,表示雖然輸入,但還沒有到達進入系統時刻
typedef enum ProcessState{Executing, Ready, Finish, Unarrive} STATE;

//程序控制塊PCB的定義
typedef struct process_pcb{ int ID;//程序標識 int priority;//程序優先數,值越大,優先順序越高 int arrive_time;//程序到達時間,以時間片為單位 int service_time;//程序需要總的服務時間,以時間片為單位 int start_time;//程序開始執行時間,以時間片為單位 int end_time;//程序結束時間,以時間按片為單位 int all_time;//程序仍然需要的執行時間,以時間片為單位 int cpu_time;//程序已佔用CPU時間,以時間片為單位 STATE state;//程序狀態
}PCB; const char* StateString[] = {"Executing","Ready", "Finish", "--"};//用於列印三種狀態 PCB * running_process = NULL;//當前執行任務 vector<PCB>input_queue;//輸入佇列,存放到達時刻大於當前時刻的程序 vector<PCB>ready_queue;//就緒佇列 vector<PCB>finish_queue;//完成佇列 bool cmp_arrive_time(const PCB a, const PCB b);//輸入佇列按程序到達時間排序函式
bool cmp_priority(const PCB a, const PCB b);//就緒佇列按程序優先數排序函式 void input_process();//輸入程序資訊 int select_policy();//選擇程序排程策略 void print_all(int current);//列印所有程序資訊 void FCFS();//先來先服務演算法 void round_robin();//時間片輪轉演算法 void dynamic_prio();//動態優先順序演算法 int main(){ cout<<"========================================================\n"; cout<<" 模擬實現程序排程功能\n"; cout<<"========================================================\n"; input_process();//輸入程序資訊 print_all(-1);//-1表示列印所有程序的初始狀態 int policy = select_policy(); switch(policy){ case 1: FCFS(); break; case 2: round_robin(); break; case 3: dynamic_prio(); break; default: FCFS(); break; } return 0; } void input_process(){//輸入程序資訊 int num; cout<<"請輸入程序數量: "; cin>>num; PCB pro;//定義程序的程序控制塊 for(int i=0; i<num;i++){ cout<<"請輸入第"<<i<<"個程序的到達時間、服務時間及優先順序(以空格隔開): "; cin>>pro.arrive_time>>pro.service_time>>pro.priority; pro.ID = i; pro.all_time = pro.service_time; pro.cpu_time = 0; pro.start_time = -1;//開始及幾萬數時間預設wier-1,表示程序尚未被排程過 pro.end_time = -1; pro.state = Unarrive;//初始化為尚未進入系統 input_queue.push_back(pro); } sort(input_queue.begin(),input_queue.end(),cmp_arrive_time);//按到達時間升序排隊 } int select_policy(){//選擇程序排程策略 cout<<"請選擇排程演算法(輸入數字1、2、3選擇): \n"; cout<<"1.先來先服務演算法(FCFS) \n"; cout<<"2.時間片輪轉法(Round-robin) \n"; cout<<"3.動態優先順序排程演算法(DynamicPriority)\n"; int n; cout<<"請選擇排程演算法序號: "; while(scanf("%d", &n) == 1){ if(n>3||n<1) cout<<"對不起,輸入有誤,請重新輸入!\n"; else break; } return n; } void FCFS(){//先來先服務排程演算法 int chip=0;//初始的時間片為0 bool need_schedule = true;//需要排程的標誌,預設為true while(1){//如果當前沒有正在執行程序,並且輸入佇列和就緒佇列都為空,則所有程序完成 if(!running_process && input_queue.empty() && ready_queue.empty()) break; while(!input_queue.empty()){//將到達時間小於等於當前時間片的程序從輸入佇列移到就緒佇列中 PCB pro = input_queue[0]; if(pro.arrive_time <= chip){ pro.state = Ready; ready_queue.push_back(pro);//放入就緒列隊尾 input_queue.erase(input_queue.begin()+0);//從輸入佇列中刪除 } else{ break; } } if(need_schedule && !ready_queue.empty()){//判斷是否需要排程,如果需要就從就緒佇列取出隊首程序進行排程 running_process = new PCB; *running_process = ready_queue[0];//取出就緒隊首程序 ready_queue.erase(ready_queue.begin()+0);//從就緒佇列中刪除之 running_process->start_time = chip;//排程程序開始執行 running_process->state = Executing; need_schedule = false; } print_all(chip);//列印當前時刻所有程序的資訊 if(running_process){//當前執行任務完成一個時間片,更改其資訊 running_process->cpu_time += 1; running_process->all_time -= 1; if(running_process->all_time == 0){//任務執行結束 running_process->end_time = chip+1; running_process->state = Finish; finish_queue.push_back(*running_process);//將其放入完成佇列 delete running_process; running_process = NULL; need_schedule = true; } else{ need_schedule = false; } } chip+=1; } print_all(chip); } bool cmp_arrive_time(const PCB a, const PCB b){//按程序到達時間升序排列 return a.arrive_time < b.arrive_time; } bool cmp_priority(const PCB a, const PCB b){ if(a.priority != b.priority){ return a.priority > b.priority; } else{ return a.arrive_time < b.arrive_time; } } void print_process(PCB * pro){//列印單個程序資訊 if(pro == NULL){ return; } printf("%4d%10d%10d%6d%15s",pro->ID,pro->arrive_time,pro->service_time,pro->priority,StateString[pro->state]); //如果程序尚未開始,則開始時間、結束時間以及剩餘時間以”--“來表示 //如果程序已經開始,但尚未結束,則其時間以”--“表示 if(pro->start_time == -1){ cout<<setw(10)<<"--"<<setw(10)<<"--"<<setw(10)<<"--"; } else{ if(pro->end_time == -1){ cout<<setw(10)<<pro->start_time<<setw(10)<<"--"<<setw(10)<<pro->all_time; } else{ cout<<setw(10)<<pro->start_time<<setw(10)<<pro->end_time<<setw(10)<<pro->all_time; } } if(pro->state == Finish){//程序結束,統計其週轉時間及加權週轉時間 cout<<setw(10)<<pro->end_time - pro->start_time<<setw(10)<<(float)(pro->end_time - pro->arrive_time)/(float)pro->service_time<<endl; } else{ cout<<setw(10)<<"--"<<setw(10)<<"--"<<endl; } } void print_all(int current){//列印所有程序的資訊,-1為列印程序初始輸入狀態 if(current == -1){ cout<<"\n程序初始狀態: \n"; } else{ cout<<"\n當前時刻為: "<<current<<endl; } printf(" 程序號 到達時間 服務時間 優先順序 狀態 開始時間 結束時間 剩餘時間 週轉時間 帶權週轉時間\t\n"); //列印正在執行的程序 if(running_process != NULL){ print_process(running_process); } vector<PCB>::iterator it; for(it = ready_queue.begin();it != ready_queue.end();it++){//列印就緒佇列中的程序 print_process(&(*it)); } for(it = finish_queue.begin();it != finish_queue.end();it++){//列印完成佇列中的程序 print_process(&(*it)); } for(it = input_queue.begin();it != input_queue.end();it++){//列印仍然在輸入佇列中的程序 print_process(&(*it)); } cout<<"\n"; } void round_robin(){//時間片輪轉法 int chip=0; bool need_schedule = true;//初始時間片為0 while(1){//如當前無執行程序,同時輸入佇列和就緒佇列都為空,則所有程序完成 if(!running_process && input_queue.empty() && ready_queue.empty()){ break; } while(!input_queue.empty()){//將到達時間小於等於當前時間片的程序從輸入佇列移到就緒佇列中 PCB pro = input_queue[0]; if(pro.arrive_time <= chip){ pro.state = Ready; ready_queue.push_back(pro); input_queue.erase(input_queue.begin()+0); } else break; } if(need_schedule && !ready_queue.empty()){//判斷是否需要排程,如需要則取出就緒佇列隊首程序進行排程 running_process = new PCB; *running_process = ready_queue[0];//從就緒佇列中取出 ready_queue.erase(ready_queue.begin()+0);//從就緒佇列中刪除 if(running_process->start_time == -1){//首次執行 running_process->start_time = chip; } running_process->state = Executing; need_schedule = false; } print_all(chip);//列印當前時刻所有程序的資訊 if(running_process){//當前執行任務完成一個時間片,更改其資訊 running_process->cpu_time += 1; running_process->all_time -= 1; if(running_process->all_time == 0){//任務執行結束 running_process->end_time = chip+1; running_process->state = Finish; finish_queue.push_back(*running_process);//將其放入完成佇列 delete running_process; running_process = NULL; need_schedule = true; } else{ if(!ready_queue.empty()){ running_process->state = Ready; ready_queue.push_back(*running_process);//將其放回就緒佇列中 delete running_process; running_process=NULL; need_schedule = true; } else{ need_schedule = false; } } } chip+=1; } print_all(chip); } void dynamic_prio(){ int chip=0;//初始的時間片為0 bool need_schedule = true;//需要排程的標誌,預設為true while(1){//如果當前沒有正在執行程序,並且輸入佇列和就緒佇列都為空,則所有程序完成 if(!running_process && input_queue.empty() && ready_queue.empty()) break; while(!input_queue.empty()){//將到達時間小於等於當前時間片的程序從輸入佇列移到就緒佇列中 PCB pro = input_queue[0]; if(pro.arrive_time <= chip){ pro.state = Ready; ready_queue.push_back(pro);//放入就緒列隊尾 input_queue.erase(input_queue.begin()+0);//從輸入佇列中刪除 } else{ break; } } if(!ready_queue.empty()){ sort(ready_queue.begin(),ready_queue.end(),cmp_priority);//按優先順序降序排列 } if(need_schedule && !ready_queue.empty()){//判斷是否需要排程,如果需要就從就緒佇列取出隊首程序進行排程 running_process = new PCB; *running_process = ready_queue[0];//取出就緒隊首程序 ready_queue.erase(ready_queue.begin()+0);//從就緒佇列中刪除之 running_process->start_time = chip;//排程程序開始執行 running_process->state = Executing; need_schedule = false; } print_all(chip);//列印當前時刻所有程序的資訊 if(running_process){//當前執行任務完成一個時間片,判斷任務是否完成,更改其資訊 running_process->cpu_time += 1; running_process->all_time -= 1; if(running_process->all_time == 0){//任務執行結束 running_process->end_time = chip+1; running_process->state = Finish; finish_queue.push_back(*running_process);//將其放入完成佇列 delete running_process; running_process = NULL; need_schedule = true; } else{//任務未完成,如果就緒佇列仍有任務,且優先順序大於本任務優先順序,則輪轉排程,否則不排程 if(running_process->priority > 1){ running_process -> priority -= 1; } if(ready_queue.empty() && ready_queue[0].priority > running_process->priority){ running_process->state = Ready; ready_queue.push_back(*running_process);//將其放回就緒佇列 delete running_process; running_process = NULL; need_schedule = true; } else{ need_schedule = false; } } } chip+=1; } print_all(chip); }