處理機排程演算法C語言實現(註釋得當!!)
阿新 • • 發佈:2018-12-26
/*
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);
}