1.实验目的
通过这次实验,加深对进程概念的理解,进一步掌握进程状态的转变、进程调度的策略及对系统性能的评价方法。
2.实验内容
问题描述:
设计程序模拟进程的先来先服务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)输出:要求输出计算出来的每个进程的周转时间、带权周转时间、所有进程的平均周转时间以及带权平均周转时间。
实现提示:
用C++语言实现提示:
1)程序中进程调度时间变量描述如下:
static int MaxNum=100;
int ArrivalTime[MaxNum];
int ServiceTime[MaxNum];
int FinishTime[MaxNum];
int WholeTime[MaxNum];
double WeightWholeTime[MaxNum];
double AverageWT_FCFS,AverageWT_SJF;
double AverageWWT_FCFS,AverageWWT_SJF;
2)进程调度的实现过程如下:
变量初始化;
接收用户输入n,T1, … ,Tn,S1, … ,Sn;算法选择1-FCFS,2-SJF;
按照选择算法进行进程调度,计算进程的完成时间、周转时间和带权周转时间;
计算所有进程的平均周转时间和平均带权周转时间;
按格式输出调度结果。
实验要求:
1)上机前认真复习FCFS和SJF进程调度调度算法,熟悉进程调度的执行过程;
2)上机时独立编程、调试程序;
3)根据具体实验要求,完成好实验报告(包括实验的目的、内容、要求、源程序、实例运行结果截图、发现的问题以及解决方法)。
3.实验开发环境
CodeBlocks编译器
4.程序代码如下及其算法说明
#include <iostream>
#include <iomanip>
#include <cstdlib>
#define MaxNum 100
using namespace std;
int ArrivalTime[MaxNum]= {0,1,2,3,4}; //到达时间
int ServiceTime[MaxNum]= {4,3,5,2,4}; //服务时间
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]; //判断FCFS算法中进程是否被执行
bool isFinished_SJF[MaxNum]; //判断SJF算法中进程是否被执行
static int n=5;
void Initial() //进行初始化
{
for (int i=0; i<n; i++)
{
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<<"用户输入的进程个数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;
cout<<endl;
}
//找到第一个进程
int find_firstProcess()
{
int first = n-1;
for (int i=0; i<n; i++)
{
if (ArrivalTime[i]<=ArrivalTime[first])
{
first = i;
}
}
return first;
}
void result()
{
cout<<endl;
cout<<setw(10)<<"进程名"<<" ";
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()
{
int startWorkTime = 0; //表示每个进程开始执行的时间 = 当前进行的进程之前的所有进程的服务时间之和
int first = find_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]; //带权周转时间 = 周转时间/服务时间
//找到接下去的进程
for (int i=1; i<n; i++)
{
int 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]) //筛选出最先到达的进程
{
cout<<ArrivalTime[nextProcess]<<endl;
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] = WholeTime[nextProcess]/ServiceTime[nextProcess]; //带权周转时间 = 周转时间/服务时间
}
//计算平均周转时间和平均带权周转时间
double totalWT = 0;
double totalWWT = 0;
for (int i=0; i<n; i++)
{
totalWT+=WholeTime[i];
totalWWT+=WeightWholeTime[i];
}
AverageWT_FCFS = totalWT/n; //平均周转时间=周转时间之和/进程数n
AverageWWT_FCFS = totalWWT/n; //平均带权周转时间=带权周转时间/进程数n
//调用输出函数
result();
cout<<"平均周转时间="<<AverageWT_FCFS<<endl;
cout<<"平均带权周转时间="<<AverageWWT_FCFS<<endl;
cout<<endl;
}
void SJF()
{
int startWorkTime_SJF = 0; //表示开始执行时间 = 当前进程之前的所有服务时间之和
int first = find_firstProcess(); //获得第一个进程
isFinished_SJF[first] = true;
FinishTime[first] = ArrivalTime[first] + ServiceTime[first];
startWorkTime_SJF += ServiceTime[first]; //下一个进程的开始执行时间
WholeTime[first] = FinishTime[first] - ArrivalTime[first]; //周转时间 = 完成时间 - 到达时间
WeightWholeTime[first] = WholeTime[first]/ServiceTime[first]; //带权周转时间 = 周转时间/服务时间
//获得下一个进程的下标
for (int i=1; i<n; i++)
{
int nextProcess = n;
for (int j=0; j<n; j++)
{
if (!isFinished_SJF[j])
{
if (ArrivalTime[j]<=startWorkTime_SJF)//到达时间小于已经进行的时间
{
if (nextProcess==n)
{
nextProcess = j;
}
else
{
if (ServiceTime[nextProcess]>ServiceTime[j])
{
nextProcess = j; //获得运行时间最短的作业的下标
}
}
}
}
}
//对获得的进程进行处理
isFinished_SJF[nextProcess] = true;
FinishTime[nextProcess] = ServiceTime[nextProcess] + startWorkTime_SJF;
startWorkTime_SJF += ServiceTime[nextProcess];
WholeTime[nextProcess] = FinishTime[nextProcess] - ArrivalTime[nextProcess];
WeightWholeTime[nextProcess] = (double)WholeTime[nextProcess]/ServiceTime[nextProcess];
}
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;
//输出检测
result();
cout<<"平均周转时间="<<AverageWT_SJF<<endl;
cout<<"平均带权周转时间="<<AverageWWT_SJF<<endl;
cout<<endl;
}
//选择算法
void choose_Way()
{
cout<<"请选择算法 ①FCFS OR ②SJF"<<endl;
int way;
cin>>way;
if (way==1)
{
FCFS();
}
else if(way==2)
{
SJF();
}
else
{
cout<<"请选择正确序号”"<<endl;
cout<<endl;
choose_Way();//回调函数
}
}
//调用mian函数
int main()
{
Initial();
input();
choose_Way();
system("pause");
choose_Way();
return 0;
}
代码说明:算法分为对数组初始化Initial(),然后给数组赋值input(),然后用户选择方法choose_way()。
FCFS先来先服务采用的算法如下:
//找到接下去的进程
for (int i=1; i<n; i++)
{
int 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]) //筛选出最先到达的进程
{
cout<<ArrivalTime[nextProcess]<<endl;
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] = WholeTime[nextProcess]/ServiceTime[nextProcess]; //带权周转时间 = 周转时间/服务时间
}
FCFS思路:首先先排除已经服务过的进程,然后for(i)循环来执行剩下的进程,通过for(i)中的for(j)循环找到剩下未执行的进制中最早到达且到达时间小于已经服务的时间的进程来进行,以此类推依次找到完成剩下的进程
SJF算法如下:
for (int i=1; i<n; i++)
{
int nextProcess = n;
for (int j=0; j<n; j++)
{
if (!isFinished_SJF[j])
{
if (ArrivalTime[j]<=startWorkTime_SJF)//到达时间小于已经进行的时间
{
if (nextProcess==n)
{
nextProcess = j;
}
else
{
if (ServiceTime[nextProcess]>ServiceTime[j])
{
nextProcess = j; //获得运行时间最短的作业的下标
}
}
}
}
}
//对获得的进程进行处理
isFinished_SJF[nextProcess] = true;
FinishTime[nextProcess] = ServiceTime[nextProcess] + startWorkTime_SJF;
startWorkTime_SJF += ServiceTime[nextProcess];
WholeTime[nextProcess] = FinishTime[nextProcess] - ArrivalTime[nextProcess];
WeightWholeTime[nextProcess] = (double)WholeTime[nextProcess]/ServiceTime[nextProcess];
}
SJF思路:首先先排除已经服务过的进程,然后for(i)循环来执行剩下的进程,通过for(i)中的for(j)循环找到剩下未执行的进制中服务时间最短且到达时间小于已经服务的时间的进程来进行,以此类推依次找到完成剩下的进程
5.调试过程和运行结果
FCFS算法结果如下
SJF算法如下