1. 程式人生 > >1】先來先服務FCFS和短作業優先SJF程序排程演算法

1】先來先服務FCFS和短作業優先SJF程序排程演算法

// 作業系統_實驗一.cpp : 定義控制檯應用程式的入口點。
//
/*
//實驗題目:先來先服務FCFS和短作業優先SJF程序排程演算法
*******概念*******
1. 先來先服務FCFS:
2. 短作業優先SJF:
3. 高階排程:根據某種演算法,在外存中把處於後備佇列中的那些作業調入記憶體,當作業完成時做善後處理
4. 中級排程
5. 低階排程:物件是程序(或核心級執行緒);三個基本機制:排隊器、分派器、上下文切換機制
6. 排程方式和演算法的若干準則
	1)面向使用者的準則:週期時間短、響應時間快、截止時間的保證、優先權準則
	2)面向系統的準則:系統吞吐量高、處理機利用率好、各類資源的平衡利用
7. 排程演算法:根據系統的資源分配策略所規定的資源分配演算法
8. FCFS排程演算法有利於CPU繁忙型的作業,而不利於I/O繁忙型的作業或程序

*******實驗要求*********
1. 先來先服務排程演算法FCFS:
	1)是一種最簡單的排程演算法,適用於作業排程和程序排程
	2)每次排程都是從後備佇列中選擇一個或者多個最先進入該佇列的作業,將它們調入記憶體,分配資源,建立程序,然後放入就緒佇列
	3)FCFS演算法比較有利於長作業(程序),不利於短作業(程序)
	4)既可用於作業排程,也可用於程序排程
2. 週轉時間 = 完成時間 - 到達時間
   帶權週轉時間 = 週轉時間/服務時間

*/

#include <iostream>
#include <iomanip>
using namespace std;

#define MaxNum 100

//typedef struct
//{
//	int  ArrivalTime[MaxNum];  //到達時間
//	int  ServiceTime[MaxNum];  //服務時間
//	int  FinishTime[MaxNum];   //完成時間
//
//
//}Process;

/* 演算法思想:
   1. Initial()進行初始化
   2. input()對到達時間和服務時間進行輸入
   3. get_firstProcess()獲得第一個程序,FCFS和SJF演算法的實現相同
   4. FCFS()對演算法進行處理
   5. SJF()對演算法進行處理
   6. choose_Algorithm();對實現演算法的類別進行選擇:具有容錯性特徵
*/

//相同的陣列下標對應同一個程序的資訊
int  ArrivalTime[MaxNum];  //到達時間
int  ServiceTime[MaxNum];  //服務時間
int  FinishTime[MaxNum];   //完成時間
int  WholeTime[MaxNum];    //週轉時間
double  WeightWholeTime[MaxNum];      //帶權週轉時間
double AverageWT_FCFS,AverageWT_SJF;  //FCFS演算法的平均週轉時間,SJF演算法的平均週轉時間
double AverageWWT_FCFS,AverageWWT_SJF; //FCFS演算法的平均帶權週轉時間,SJF演算法的平均帶權週轉時間

bool isFinished_FCFS[MaxNum];
bool isFinished_SJF[MaxNum];

static int n;

void Initial()  //確定程序個數後再初始化
{
	cout<<"請輸入作業(程序)個數n=";
	cin>>n;

	for (int i=0;i<n;i++)
	{
		ArrivalTime[i] = 0;
		ServiceTime[i] = 0;
		FinishTime[i] = 0;
		WholeTime[i] = 0;
		WeightWholeTime[i] = 0;
		AverageWT_FCFS = 0;
		AverageWT_SJF = 0;
		AverageWWT_FCFS = 0;
		AverageWWT_SJF = 0;
		isFinished_FCFS[i] = false;
		isFinished_SJF[i] = false;
	}
}

void input()
{
	cout<<"請分別輸入每個程序的到達時間:"<<endl;
	for (int i=0;i<n;i++)
	{
		cin>>ArrivalTime[i];
	}

	cout<<"請分別輸入每個程序的服務時間:"<<endl;
	for (int i=0;i<n;i++)
	{
		cin>>ServiceTime[i];
	}

	//輸出使用者輸入的資訊
	cout<<"******************************************************"<<endl;
	cout<<"使用者輸入的程序個數n="<<n<<endl;

	cout<<"使用者輸入的服務時間分別為:"<<endl;
	for (int i=0;i<n;i++)
	{
		cout<<ArrivalTime[i]<<" ";
	}
	cout<<endl;

	cout<<"使用者輸入的服務時間分別為:"<<endl;
	for (int i=0;i<n;i++)
	{
		cout<<ServiceTime[i]<<" ";
	}
	cout<<endl<<"******************************************************"<<endl;
}

int get_firstProcess()
{
	int first = MaxNum;
	for (int i=0;i<n;i++)
	{
		if (ArrivalTime[i]<=ArrivalTime[first])
		{
			first = i;
		}
	}
	return first;
}

void display()
{
	cout<<"******************************************************"<<endl;
	cout<<"程序相關資訊如下:"<<endl;
	cout<<setw(10)<<"程序名(ID)"<<" ";
	cout<<setw(10)<<"到達時間"<<" ";
	cout<<setw(10)<<"服務時間"<<" ";
	cout<<setw(10)<<"完成時間"<<" ";
	cout<<setw(10)<<"週轉時間"<<" ";
	cout<<setw(10)<<"帶權週轉時間"<<endl;
	for (int i = 0;i<n;i++)
	{
		cout<<setw(10)<<i+1<<" ";
		cout<<setw(10)<<ArrivalTime[i]<<" ";
		cout<<setw(10)<<ServiceTime[i]<<" ";
		cout<<setw(10)<<FinishTime[i]<<" ";
		cout<<setw(10)<<WholeTime[i]<<" ";
		cout<<setw(10)<<WeightWholeTime[i]<<" "<<endl;
	}
}

void FCFS()
{
	/*
		1. 找到最先到達的程序的座標,並計算相關資訊
		2. 依次找到接下去到達的程序
	*/

	int startWorkTime = 0;  //表示開始執行時間 = 當前程序之前的所有服務時間之和
	int first = get_firstProcess();  //獲得第一個程序

	isFinished_FCFS[first] = true;
	FinishTime[first] = ArrivalTime[first] + ServiceTime[first];
	startWorkTime += ServiceTime[first];   //下一個程序的開始執行時間
	WholeTime[first] = FinishTime[first] - ArrivalTime[first];   //週轉時間 = 完成時間 - 到達時間
	WeightWholeTime[first] = WholeTime[first]/ServiceTime[first]; //帶權週轉時間 = 週轉時間/服務時間

	//接下去的程序
	int nextProcess = n; //初始化下一個程序的下標超出界限

	for (int i=1;i<n;i++)
	{
		nextProcess = n;  //每次對下一個程序的下標進行更新
		for (int j=0;j<n;j++)
		{
			if (!isFinished_FCFS[j])  //表示當前程序還未完成相關資訊的計算
			{
				if (ArrivalTime[j]<=startWorkTime)  //滿足到達時間小於等於開始執行時間的情況下
				{
					if (nextProcess==n)
					{
						nextProcess = j;
					}
					else
					{
						if (ArrivalTime[nextProcess]>ArrivalTime[j])  //篩選出最先到達的程序
						{
							nextProcess=j;    //獲得當前程序中:最先到達的程序
						}
					}
				}
			}
		}//for(j)
		//獲得當前需要處理的程序nextProcess後,對相關資訊進行計算
		isFinished_FCFS[nextProcess] = true;
		FinishTime[nextProcess] = ServiceTime[nextProcess] + startWorkTime;
		startWorkTime += ServiceTime[nextProcess];  //獲得下一個程序對應的“開始執行時間”
		WholeTime[nextProcess] = FinishTime[nextProcess] - ArrivalTime[nextProcess];
		WeightWholeTime[nextProcess] = (double)WholeTime[nextProcess]/ServiceTime[nextProcess];

	}//for(i)

	//計算平均週轉時間和平均帶權週轉時間
	double totalWT = 0;
	double totalWWT = 0;
	for (int i=0;i<n;i++)
	{
		totalWT+=WholeTime[i];
		totalWWT+=WeightWholeTime[i];
	}
	AverageWT_FCFS = totalWT/n;
	AverageWWT_FCFS = totalWWT/n;

	//輸出檢測
	display();
	cout<<"平均週轉時間="<<AverageWT_FCFS<<endl;
	cout<<"平均帶權週轉時間="<<AverageWWT_FCFS<<endl;
	cout<<"******************************************************"<<endl;
}

void SJF()
{
	//與SCSF類似,相同的方法獲得第一個程序
	int startWorkTime_SJF = 0;  //表示開始執行時間 = 當前程序之前的所有服務時間之和
	//第一個程序的處理
	int first = get_firstProcess();  //獲得第一個程序

	isFinished_SJF[first] = true;
	FinishTime[first] = ArrivalTime[first] + ServiceTime[first];
	startWorkTime_SJF += ServiceTime[first];   //下一個程序的開始執行時間
	WholeTime[first] = FinishTime[first] - ArrivalTime[first];   //週轉時間 = 完成時間 - 到達時間
	WeightWholeTime[first] = (double)WholeTime[first]/ServiceTime[first]; //帶權週轉時間 = 週轉時間/服務時間

	//獲得下一個程序的下標
	
	int nextProcess_SJF = n;
	for (int i=1;i<n;i++)
	{
		nextProcess_SJF = n;
		for (int j=0;j<n;j++)
		{
			if (!isFinished_SJF[j])
			{
				if (ArrivalTime[j]<=startWorkTime_SJF)
				{
					if (nextProcess_SJF==n)
					{
						nextProcess_SJF = j;
					}
					else
					{
						if (ServiceTime[nextProcess_SJF]>ServiceTime[j])
						{
							nextProcess_SJF = j;   //獲得執行時間最短的作業的下標
						}
					}
				}
			}
		}//for(j)
		
		//對獲得的程序進行處理
		isFinished_SJF[nextProcess_SJF] = true;
		FinishTime[nextProcess_SJF] = ServiceTime[nextProcess_SJF] + startWorkTime_SJF;
		startWorkTime_SJF += ServiceTime[nextProcess_SJF]; 
		WholeTime[nextProcess_SJF] = FinishTime[nextProcess_SJF] - ArrivalTime[nextProcess_SJF];
		WeightWholeTime[nextProcess_SJF] = (double)WholeTime[nextProcess_SJF]/ServiceTime[nextProcess_SJF];

	}//for(i)

	double totalWT = 0;
	double totalWWT = 0;
	for (int i=0;i<n;i++)
	{
		totalWT+=WholeTime[i];
		totalWWT+=WeightWholeTime[i];
	}
	AverageWT_SJF = totalWT/n;
	AverageWWT_SJF = totalWWT/n;

	//輸出檢測
	display();
	cout<<"平均週轉時間="<<AverageWT_SJF<<endl;
	cout<<"平均帶權週轉時間="<<AverageWWT_SJF<<endl;
	cout<<"******************************************************"<<endl;
}

void choose_Algorithm()
{
	cout<<"請選擇演算法“1-FCFS,2-SJF”"<<endl;
	int choose;
	cin>>choose;
	if (choose==1)
	{
		FCFS();
	}
		else if(choose==2)
		{
			SJF();
		}
	else
	{
		cout<<"請輸入正確的選擇“1-FCFS,2-SJF”"<<endl;
		cout<<"******************************************************"<<endl;
		choose_Algorithm();  //遞迴呼叫,實現排除錯誤的選擇也可以繼續輸入
	}
}



int main()
{
	Initial();
	input();
	choose_Algorithm();
	system("pause");
	return 0;
}