实验原理:
短进程优先算法是以作业的长短来计算优先级,作业越短,其优先级越高。作业的长短是以作业所要求的运行时间来衡量的。在把短作业优先调度算法用于作业调度时,它将从外存的作业后备队列中选择若干个估计运行时间最短的作业,优先将它们调入内存运行。
完成时间 = 开始时间 + 需要运行时间
周转时间 = 完成时间 - 到达时间
带权周转时间 = 周转时间 / 需要运行时间
实验内容:
按作业提交的/到达的(到达后备队列的时间)先后次序从外存后备队列中选择几个最先进入该队列的作业为他们分配资源、创建进程,然后再放入就绪队列。
每个作业由一个作业控制块JCB表示,JCB可以包含如下信息∶作业名、提交时间、所需的运行时间、作业状态等等。
作业的状态可以是等待W(Wait)、运行R(Run)和完成F(Finish)三种状态之一。每个作业的最初状态总是等待W。各个等待的作业按照提交时刻的先后次序排队。
每个作业完成后要输出该作业的开始运行时刻、完成时刻、周转时间和带权周转时间,这一组作业完成后计算并输出这组作业的平均周转时间、平均带权周转时间。
#include <iostream>
#include <string.h>
#include <iomanip>
struct job
{
char name[10]; //作业的名字
int starttime; //作业到达系统时间
int needtime; //作业服务时间
int runtime; //作业周转时间
int endtime; //作业结束时间
int flag=0; //作业完成标志
char state='W'; //作业状态,一开始都默认为就绪
double dqzz_time; //带权周转时间
};
void sjf(struct job jobs[50],int n){
int i=0,j=0,k,temp,count=0,min_needtime,min_starttime,t_time,flag1;
char t_name[10];
int nowtime=0;
for(i=0;i<n;i++) //按作业到达系统时间进行排序,最早到达的排在最前面
{
min_needtime=jobs[i].needtime;
temp=i;
for(j=i;j<n;j++) //按作业到达系统时间进行排序,最早到达的排在最前面
{
if(jobs[j].needtime<min_needtime)
{
temp=j;
min_needtime=jobs[j].needtime;
}
}
if(temp!=i)
{
jobs[40]=jobs[temp];
for(k=temp-1;k>=i;k--)
{
jobs[k+1]=jobs[k];
}
jobs[i]=jobs[40];
}
}
while(count<n){
temp=1000;
flag1=0;
min_needtime=1000;
min_starttime=1000;
for(i=0;i<n;i++){
if(jobs[i].flag==0){
if(jobs[i].starttime<=nowtime)
{
flag1=1;
if(jobs[i].needtime<min_needtime){
min_needtime=jobs[i].needtime;
temp=i;
}
}
}
}
if(flag1==0)
{
for(i=0;i<n;i++){
if(jobs[i].flag==0){
if(jobs[i].starttime<min_starttime){
min_starttime=jobs[i].starttime;
temp=i;
}
}
}
nowtime=jobs[temp].starttime+jobs[temp].needtime;
jobs[temp].endtime=nowtime;
jobs[temp].flag=1;
jobs[temp].runtime=jobs[temp].endtime-jobs[temp].starttime;
jobs[temp].dqzz_time=float(jobs[temp].runtime)/jobs[temp].needtime;
count++;
}
else{
nowtime+=jobs[temp].needtime;
jobs[temp].endtime=nowtime;
jobs[temp].flag=1;
jobs[temp].runtime=jobs[temp].endtime-jobs[temp].starttime;
jobs[temp].dqzz_time=float(jobs[temp].runtime)/jobs[temp].needtime;
count++;
}
}
}
void print(struct job jobs[50],int n)
{
int i;
double avertime;
double dqzz_avertime;
int sum_runtime=0;
double sum_time=0.00;
printf("作业名 到达时间 运行时间 完成时间 周转时间 带权周转时间\n");
for(i=0;i<n;i++)
{
printf("%s %2d %2d %2d %2d %.2f\n",jobs[i].name,jobs[i].starttime,jobs[i].needtime,jobs[i].endtime,jobs[i].runtime,jobs[i].dqzz_time);
sum_runtime=sum_runtime+jobs[i].runtime;
sum_time=sum_time+jobs[i].dqzz_time;
}
avertime=sum_runtime*1.0/n;
dqzz_avertime=sum_time*1.000/n;
printf("平均周转时间:%.2f \n",avertime);
printf("平均带权周转时间:%.3f \n",dqzz_avertime);
printf("\n");
}
int main()
{
struct job jobs[50];
int n,i; //n个作业
printf("请输入作业个数:");
scanf("%d",&n);
printf("请输入各作业的信息(格式:作业名 到达时间 服务时间):\n");
for(i=0;i<n;i++)
{
scanf("%s",jobs[i].name); //作业名
scanf("%d",&jobs[i].starttime);//到达时间
scanf("%d",&jobs[i].needtime);//运行(服务时间)时间
}
printf("\n");
sjf(jobs,n);
printf("先来先服务(FCFS)调度算法运行结果:\n");
print(jobs,n);
}
运行结果
由于忘记改了,大家记得把最后一行的printf里的文字改为短作业优先算法,sjf
11.9更新
对代码做出了一些修改,加了一些注释,并对输出按照endtime进行排序,这样看起来更直观
#include <iostream>
#include <string.h>
#include <iomanip>
struct job
{
char name[10]; //作业的名字
int starttime; //作业到达系统时间
int needtime; //作业服务时间
int runtime; //作业周转时间
int endtime; //作业结束时间
int flag=0; //作业完成标志
char state='W'; //作业状态,一开始都默认为就绪
double dqzz_time; //带权周转时间
};
void sjf(struct job jobs[50],int n){
int i=0,j=0,k,temp,count=0,min_needtime,min_starttime,t_time,flag1;
char t_name[10];
int nowtime=0;
for(i=0;i<n;i++) //按作业所需运行时间排序,短的排在最前面
{
min_needtime=jobs[i].needtime;//n轮循环,每次都把job[j]与job[i]的所需运行时间相比较,从而找到位于job[i]后的最短的运行时间
temp=i;
for(j=i;j<n;j++)
{
if(jobs[j].needtime<min_needtime)
{
temp=j;
min_needtime=jobs[j].needtime;
}
}
if(temp!=i)//存在更短的运行时间
{
jobs[40]=jobs[temp];//中间变量
for(k=temp-1;k>=i;k--)//将位于jobs[temp]前的jobs向左平移
{
jobs[k+1]=jobs[k];
}
jobs[i]=jobs[40];
}
}
while(count<n){//作业未全部运行完
temp=1000;
flag1=0;
min_needtime=1000;
min_starttime=1000;
for(i=0;i<n;i++){
if(jobs[i].flag==0){
if(jobs[i].starttime<=nowtime)//存在未完成且等待的作业
{
flag1=1;
if(jobs[i].needtime<min_needtime){//找出所需运行时间最短的作业
min_needtime=jobs[i].needtime;
temp=i;
}
}
}
}
if(flag1==0)//如果所有未完成的作业都没等待
{
for(i=0;i<n;i++){
if(jobs[i].flag==0){
if(jobs[i].starttime<min_starttime){//找出最先到达的作业
min_starttime=jobs[i].starttime;
temp=i;
}
}
}
nowtime=jobs[temp].starttime+jobs[temp].needtime;//系统时间从作业到达时间开始
jobs[temp].state='r';
jobs[temp].endtime=nowtime;
jobs[temp].flag=1;
jobs[temp].runtime=jobs[temp].endtime-jobs[temp].starttime;
jobs[temp].dqzz_time=float(jobs[temp].runtime)/jobs[temp].needtime;
jobs[temp].state='f';
count++;
}
else{//有等待的作业
nowtime+=jobs[temp].needtime;//从系统时间开始运行
jobs[temp].state='r';
jobs[temp].endtime=nowtime;
jobs[temp].flag=1;
jobs[temp].runtime=jobs[temp].endtime-jobs[temp].starttime;
jobs[temp].dqzz_time=float(jobs[temp].runtime)/jobs[temp].needtime;
jobs[temp].state='f';
count++;
}
}
}
void print(struct job jobs[50],int n)
{
int i,j;
double avertime;
double dqzz_avertime;
int sum_runtime=0;
double sum_time=0.00;
for(i=0;i<n;i++) //按作业完成时间进行排序,完成早的排在最前面
{
for(j=i;j<n;j++)
{
if(jobs[j].endtime<jobs[i].endtime)
{
jobs[45]=jobs[j];
jobs[j]=jobs[i];
jobs[i]=jobs[45];
}
}
}
printf("作业名 到达时间 运行时间 完成时间 周转时间 带权周转时间\n");
for(i=0;i<n;i++)
{
printf("%s %2d %2d %2d %2d %.2f\n",jobs[i].name,jobs[i].starttime,jobs[i].needtime,jobs[i].endtime,jobs[i].runtime,jobs[i].dqzz_time);
sum_runtime=sum_runtime+jobs[i].runtime;
sum_time=sum_time+jobs[i].dqzz_time;
}
avertime=sum_runtime*1.0/n;
dqzz_avertime=sum_time*1.000/n;
printf("平均周转时间:%.2f \n",avertime);
printf("平均带权周转时间:%.3f \n",dqzz_avertime);
printf("\n");
}
int main()
{
struct job jobs[50];
int n,i; //n个作业
printf("请输入作业个数:");
scanf("%d",&n);
printf("请输入各作业的信息(格式:作业名 到达时间 服务时间):\n");
for(i=0;i<n;i++)
{
scanf("%s",jobs[i].name); //作业名
scanf("%d",&jobs[i].starttime);//到达时间
scanf("%d",&jobs[i].needtime);//运行(服务时间)时间
}
printf("\n");
sjf(jobs,n);
printf("先来先服务(FCFS)调度算法运行结果:\n");
print(jobs,n);
}
上述流程实现
t | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | |
w | B | BC | DBC | BEC | BEC | EC | EC | EC | C | C | C | C | ||||||
r | A | A | A | A | D | D | B | B | B | E | E | E | E | C | C | C | C | |
f | A | A | AD | AD | AD | ADB | ADB | ADB | ADB | ADBE | ADBE | ADBE |
t | 16 | 17 | 18 |
w | |||
r | C | C | |
f | ADBE | ADBE | ADBEC |
其中对于下面这部分代码,我觉得可以改进
for(i=0;i<n;i++){
if(jobs[i].flag==0){
if(jobs[i].starttime<=nowtime)//存在未完成且等待的作业
{
flag1=1;
if(jobs[i].needtime<min_needtime){//找出所需运行时间最短的作业
min_needtime=jobs[i].needtime;
temp=i;
}
}
}
}
由于本来就是先按照最短运行时间作业进行排序
只要找到了符合未完成且等待的作业,就可以break,跳出这个循环,不需要继续和后面的比较,读者可以自己试一下