操作系统—进城调度(先来先服务FCFS和短进程优先SJF)算法

本文介绍并实现了进程调度中的两种经典算法:先来先服务(FCFS)与短作业优先(SJF),通过实验对比了两种算法的性能,包括平均周转时间、平均带权周转时间和平均等待时间。
  1. 问题描述及需求分析
    设计程序模拟进程的先来先服务FCFS和短作业优先SJF调度过程。假设有n个进程分别在T1, … ,Tn时刻到达系统,它们需要的服务时间分别为S1, … ,Sn。分别采用先来先服务FCFS和短作业优先SJF进程调度算法进行调度,计算每个进程的完成时间,周转时间、带权周转时间和等待时间,并且统计n个进程的平均周转时间、平均带权周转时间和平均等待时间。最后,对两个算法做出比较评价。
  2. 实验设计
    先来先服务(FCFS)调度算法是一种最简单的调度算法,该算法既可用于作业调度,也可用于进程调度。当在作业调度中采用该算法时,每次调度都是从后备作业队列中选择一个或多个最先进入该队列的作业,将它们调入内存,为它们分配资源、创建进程,然后放入就绪队列。在进程调度中采用FCFS算法时,则每次调度是从就绪队列中选择一个最先进入该队列的进程,为之分配处理机,使之投入运行。该进程一直运行到完成或发生某事件而阻塞后才放弃处理机。

短作业优先调度算法SJF。该调度算法是从后备队列中选择一个或若干个估计运行时间最短的作业,将它们调入内存运行。为了和FCFS调度算法进行比较,我们仍利用FCFS算法中所使用的实例,并改用SJF算法重新调度,再进行性能分析。采用SJF算法后,不论是平均周转时间还是平均带权周转时间,都有较明显的改善,尤其是对短作业,其周转时间有大幅下降;而平均带权周转时间也有下降。这说明SJF调度算法能有效地降低作业的平均等待时间,提高系统吞吐量。

1、使用Initial()进行初始化。
2、使用input()对到达时间和服务时间进行输入。
3、使用get_firstProcess()获得第一个进程,FCFS和SJF算法相同。
4、使用FCFS()算法进行处理。
5、使用SJF()算法进行处理。
6、 使用choose_Algorithm();对实现算法的类别进行选择。

  1. 实验代码

#include
#include
#include
#include
using namespace std;
//相同的数组下标对应同一个进程的信息
#define MaxNum 100
vectorID;
vectorleftID;
int StartTime[MaxNum]; //开始时间
int ArrivalTime[MaxNum]; //到达时间
int ServiceTime[MaxNum]; //服务时间
int FinishTime[MaxNum]; //完成时间
int TurnArroundTime[MaxNum]; //周转时间
int WaitTime[MaxNum]; //等待时间
double WeightTurnArroundTime[MaxNum]; //带权周转时间double AverageWT_FCFS,AverageWT_SJF; // FCFS算法的平均等待时间,SJF算法的平均等待时间
double AverageTAT_FCFS, AverageTAT_SJF; //FCFS算法的平均周转时间,SJF算法的平均周转时间
double AverageWTAT_FCFS,AverageWTAT_SJF; //FCFS算法的平均带权周转时间,SJF算法的平均带权周转时间

bool isFinished_FCFS[MaxNum];
bool isFinished_SJF[MaxNum];
static int n; //进程个数n
void Initial() //确定进程个数后再初始化
{
cout<<"input the numbers of processes n = ";
cin>>n;
for (int i=0;i<n;i++)
{
ID.push_back(i+1);
StartTime[i] = 0;
ArrivalTime[i] = 0;
ServiceTime[i] = 0;
FinishTime[i] = 0;
TurnArroundTime[i] = 0;
WaitTime[i] = 0;
WeightTurnArroundTime[i] = 0;
AverageWT_FCFS = 0;
AverageWT_SJF = 0;
AverageTAT_FCFS = 0;
AverageTAT_SJF = 0;
AverageWTAT_FCFS = 0;
AverageWTAT_SJF = 0;
isFinished_FCFS[i] = false;
isFinished_SJF[i] = false;
}
}

void input()
{
cout<<“input the arrival time for each process :”<<endl;
for (int i=0;i<n;i++)
{
cin>>ArrivalTime[i];
}
cout<<“input the service time for each process :”<<endl;
for (int i=0;i<n;i++)
{
cin>>ServiceTime[i];
}

//输出用户输入的信息
cout<<"--------------------------------------------------------------------------------"<<endl;
cout<<“The input information :”<<endl;
cout<<" Process Num Arrival Time CPU Burst"<<endl;
for(int i=0; i<n; i++)
{
cout<<"\t"<<i+1<<"\t\t"<<ArrivalTime[i]<<"\t\t"<<ServiceTime[i]<<endl;
}
cout<<endl<<"--------------------------------------------------------------------------------"<<endl;
}

//根据到达时间排序
void sortArrivalTime()
{
int i,j;
int temp;
for(int i=0;i<n;i++)
{
for(int j=i+1;j<n;j++)
{
if(ArrivalTime[i] > ArrivalTime[j])
{
temp = ID[i];
ID[i] = ID[j];
ID[j] = temp;
}
}
}
}

//对已到达的进程服务时间排序
void sortServiceTime(int a)
{
int i,j;
int temp;
for(i=a;i<n;i++)
{
for(j=i+1;j<n;j++)
{
if(ServiceTime[i]>ServiceTime[j]&&ServiceTime[i]!=0 &&ServiceTime[j]!=0)
{
temp= ID[i];
ID[i]= ID[j];
ID[j]= temp;
}
}
}
}

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<<setw(10)<<“Process Num”<<"\t";
cout<<setw(10)<<“Start Time”<<"\t";
cout<<setw(10)<<“End Time”<<"\t";
cout<<setw(13)<<“Ready Queue”<<endl;
for (int i = 0; i < n; i++)
{
cout<<setw(10)<<i+1<<"\t";
cout<<setw(10)<<StartTime[i]<<"\t";
cout<<setw(10)<<FinishTime[i]<<"\t";
vector::iterator k = leftID.begin();
leftID.erase(k);
for (int j = 0; j < leftID.size(); j++)
{
cout<<setw(3)<<leftID[j];
}
cout<<endl;
}
cout<<"--------------------------------------------------------------------------------"<<endl;
cout<<setw(10)<<“Process Num”<<"\t";
cout<<setw(10)<<“Turnarround Time”<<"\t";
cout<<setw(10)<<“WeightedTurnarround Time”<<"\t";
cout<<setw(10)<<“Waiting Time”<<endl;
for (int i = 0; i < n; i++)
{
cout<<setw(10)<<i+1<<"\t";
cout<<setw(10)<<TurnArroundTime[i]<<"\t\t";
cout<<setw(10)<<WeightTurnArroundTime[i]<<"\t\t\t";
cout<<setw(10)<<WaitTime[i]<<endl;
}
}

void FCFS()
{
/*
1. 找到最先到达的进程的坐标,并计算相关信息
2. 依次找到接下去到达的进程
*/
int startWorkTime = 0; //表示开始执行时间 = 当前进程之前的所有服务时间之和
int first = get_firstProcess(); //获得第一个进程
sortArrivalTime();
isFinished_FCFS[first] = true;
FinishTime[first] = ArrivalTime[first] + ServiceTime[first];
StartTime[first] = startWorkTime; //上一个进程的开始执行时间
startWorkTime += ServiceTime[first]; //下一个进程的开始执行时间
WaitTime[first] = startWorkTime - ArrivalTime[first] - ServiceTime[first];
TurnArroundTime[first] = FinishTime[first] - ArrivalTime[first]; //周转时间 = 完成时间 - 到达时间
WeightTurnArroundTime[first] = TurnArroundTime[first]/ServiceTime[first]; //带权周转时间 = 周转时间/服务时间

//接下去的进程
int nextProcess = n; //初始化下一个进程的下标超出界限

for (int i=1;i<n;i++)
{
sortArrivalTime();
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;
StartTime[nextProcess] = startWorkTime;
startWorkTime += ServiceTime[nextProcess]; //获得下一个进程对应的开始执行时间
WaitTime[nextProcess] = startWorkTime - ArrivalTime[nextProcess] - ServiceTime[nextProcess];
TurnArroundTime[nextProcess] = FinishTime[nextProcess] - ArrivalTime[nextProcess];
WeightTurnArroundTime[nextProcess] = (double)TurnArroundTime[nextProcess]/ServiceTime[nextProcess];

}//for(i)

//计算平均周转时间和平均带权周转时间
double totalTAT = 0;
double totalWTAT = 0;
for (int i=0;i<n;i++)
{
totalTAT+=TurnArroundTime[i];
totalWTAT+=WeightTurnArroundTime[i];
}
AverageTAT_FCFS = totalTAT/n;
AverageWTAT_FCFS = totalWTAT/n;
leftID = ID;
display();
cout<<"Average TAT = "<<AverageTAT_FCFS<<endl;
cout<<“Average WTAT = “<<AverageWTAT_FCFS<<endl;
cout<<”--------------------------------------------------------------------------------”<<endl;
}

void SJF()
{
//与SCSF类似,相同的方法获得第一个进程
int startWorkTime_SJF = 0; //表示开始执行时间 = 当前进程之前的所有服务时间之和
//第一个进程的处理
int first = get_firstProcess(); //获得第一个进程
sortArrivalTime();
isFinished_SJF[first] = true;
FinishTime[first] = ArrivalTime[first] + ServiceTime[first];
StartTime[first] = startWorkTime_SJF; //上一个进程的开始执行时间
startWorkTime_SJF += ServiceTime[first]; //下一个进程的开始执行时间
WaitTime[first] = startWorkTime_SJF - ArrivalTime[first] - ServiceTime[first];
TurnArroundTime[first] = FinishTime[first] - ArrivalTime[first]; //周转时间 = 完成时间 - 到达时间
WeightTurnArroundTime[first] = (double)TurnArroundTime[first]/ServiceTime[first]; //带权周转时间 = 周转时间/服务时间
//获得下一个进程的下标
int nextProcess_SJF = n;
for (int i=1;i<n;i++)
{
sortServiceTime(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;
StartTime[nextProcess_SJF] = startWorkTime_SJF;
startWorkTime_SJF += ServiceTime[nextProcess_SJF];  //获得下一个进程对应的开始执行时间
WaitTime[nextProcess_SJF] = startWorkTime_SJF - ArrivalTime[nextProcess_SJF] - ServiceTime[nextProcess_SJF];
TurnArroundTime[nextProcess_SJF] = FinishTime[nextProcess_SJF] - ArrivalTime[nextProcess_SJF];
WeightTurnArroundTime[nextProcess_SJF] = (double)TurnArroundTime[nextProcess_SJF]/ServiceTime[nextProcess_SJF];

}//for(i)

double totalTAT = 0;
double totalWTAT = 0;
for (int i=0;i<n;i++)
{
totalTAT+=TurnArroundTime[i];
totalWTAT+=WeightTurnArroundTime[i];
}
AverageTAT_SJF = totalTAT/n;
AverageWTAT_SJF = totalWTAT/n;
leftID = ID;
display();
cout<<"Average TAT = "<<AverageTAT_SJF<<endl;
cout<<“Average WTAT = “<<AverageWTAT_SJF<<endl;
cout<<”--------------------------------------------------------------------------------”<<endl;
}

void choose_Algorithm()
{
while(1)
{
cout<<“请选择算法“1-FCFS,2-SJF”如果要退出请选择“0-EXIT””<<endl;
int choose;
cin>>choose;
if (choose1)
{
FCFS();
}
else if(choose
2)
{
SJF();
}
else if(choose==0)
{
break;
}
else
{
cout<<“请输入正确的选择“1-FCFS,2-SJF””<<endl;
cout<<"--------------------------------------------------------------------------------"<<endl;
choose_Algorithm(); //递归调用,实现排除错误的选择也可以继续输入
}
}
}

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

  1. 实验结果与分析
    实验结果截图
    实验过程:
    首先初始化本实验所需要的数据为默认值
    让用户输入每个进程的到达时间和服务时间
    将刚才输入的数据打印出来
    得到第一个执行的进程的具体位置下标
    让用户选择使用FCFS算法还是SJF算法进行对数据调度
    在两个算法中对全局数据数组中数据进行改变
    最后在两个算法结束后在算法函数内调用输出函数

  2. 实验心得
    通过本次实验,我对进程调度问题的相关知识有了更加深刻的理解,进一步掌握了FCFS和SJF算法,理解了使用两个算法解决进程调度问题的基本方法。以下两图是我对这两个算法的总结。
    FCFS
    SJF

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

engineer_z

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值