【实验题目】:先来先服务FCFS和短作业优先SJF进程调度算法
【实验学时】:4学时
【实验目的】
通过这次实验,加深对进程概念的理解,进一步掌握进程状态的转变、进程调度的策略及对系统性能的评价方法。
【实验内容】
问题描述:
设计程序模拟进程的先来先服务FCFS和短作业优先SJF调度过程。假设有n个进程分别在T1, … ,Tn时刻到达系统,它们需要的服务时间分别为S1, … ,Sn。分别采用先来先服务FCFS和短作业优先SJF进程调度算法进行调度,计算每个进程的完成时间,周转时间和带权周转时间,并且统计n个进程的平均周转时间和平均带权周转时间。
程序要求如下:
1)进程个数n;每个进程的到达时间T1, … ,Tn和服务时间S1, … ,Sn;选择算法1-FCFS,2-SJF。
2)要求采用先来先服务FCFS和短作业优先SJF分别调度进程运行,计算每个进程的周转时间,带权周转时间,并且计算所有进程的平均周转时间,带权平均周转时间;
3)输出:要求模拟整个调度过程,输出每个时刻的进程运行状态,如“时刻3:进程B开始运行”等等;
4)输出:要求输出计算出来的每个进程的周转时间,带权周转时间,所有进程的平均周转时间,带权平均周转时间。
【核心算法】
#include <iomanip>
#include <iostream>
#include <iomanip>
using namespace std;
#define MaxNum 100
//相同的数组下标对应同一个进程的信息
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) <<setiosflags(ios::fixed)<<setprecision(2)<< 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 << "平均周转时间=" <<setiosflags(ios::fixed)<<setprecision(2)<< AverageWT_FCFS << endl;
cout << "平均带权周转时间=" <<setiosflags(ios::fixed)<<setprecision(2)<< 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 << "平均周转时间=" <<setiosflags(ios::fixed)<<setprecision(2)<< AverageWT_SJF << endl;
cout << "平均带权周转时间=" <<setiosflags(ios::fixed)<<setprecision(2)<< 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;
}
【算法流程图】
【实例运行结果截图】
FCFS:(使用作业数据)
平均周转时间:13.2
平局带权周转时间:3.69
SJF:(使用作业数据)
平均周转时间:10.2
平局带权周转时间:1.92
【实验心得】
FCFS 和 SJF 大致步骤上都是相同的,唯一的区别就是在选择下一个要执行的进程时,FCFS选择的条件是要到达时间小于等于开始执行的时间且最先到达,而SJF选择的条件是要到达时间小于等于开始执行的时间且服务时间最短。