文章目录
- **实验六** **作业调度算法模拟**
- 一、实验目的
- 二、实验环境
- 三、实验内容和步骤
- (一)实验说明
- (二)实验内容
- 四、实验总结
- FCFS (First-Come, First-Serve)
- SJF (Shortest Job First)
- HRRF (Highest Response Ratio Next)
- HPF (Highest Priority First)
实验六 作业调度算法模拟
一、实验目的
- 掌握周转时间、等待时间、平均周转时间等概念及其计算方法。
- 理解五种常用的进程调度算法(FCFS、SJF、HRRF、HPF、RR),区分算法之间的差异性,并用C语言模拟实现各算法。
- 了解操作系统中高级调度、中级调度和低级调度的区别和联系。
二、实验环境
硬件环境:计算机一台,局域网环境;
软件环境:Windows或Linux操作系统,C语言编程环境。
三、实验内容和步骤
(一)实验说明
1.基本概念
程序:程序是指静态的指令集合,它不占用系统的运行资源,可以长久地保存在磁盘中。
进程:进程是指进程实体(由程序、数据和进程控制块构成)的运行过程,是系统进行资源分配和调度的一个独立单位。进程执行程序,但进程与程序之间不是一一对应的。通过多次运行,一个程序可以包含多个进程;通过调用关系,同一进程可以被多个程序包含(如一个DLL文件可以被多个程序运用)。
作业:作业由一组统一管理和操作的进程集合构成,是用户要求计算机系统完成的一项相对独立的工作。作业可以是完成了编译、链接之后的一个用户程序,也可以是各种命令构成的一个脚本。
作业调度:作业调度是在资源满足的条件下,将处于后备状态的作业调入内存,同时生成与作业相对应的进程,并为这些进程提供所需要的资源。作业调度适用于多道批处理系统中的批处理作业。根据作业控制块中的信息,检查系统是否满足作业的资源要求,只有在满足作业调度的资源需求的情况下,系统才能进行作业调度。
2. 基本调度算法
-
先来先服务(First-Come First-Served,FCFS)调度算法
先来先服务调度算法遵循按照进入后备队列的顺序进行调度的原则。该算法是一种非抢占式的算法,是到目前为止最简单的调度算法,其编码实现非常容易。该算法仅考虑了作业到达的先后顺序,而没有考虑作业的执行时间长短、作业的运行特性和作业对资源的要求。 -
短作业优先(Shortest-Job-First,SJF)调度算法
短作业优先调度算法根据作业控制块中指出的执行时间,选取执行时间最短的作业优先调度。本实验中规定,该算法是非抢占式的,即不允许立即抢占正在执行中的长进程,而是等当前作业执行完毕再进行调度。 -
响应比高者优先(HRRF)调度算法
FCFS调度算法只片面地考虑了作业的进入时间,短作业优先调度算法考虑了作业的运行时间而忽略了作业的等待时间。响应比高者优先调度算法为这两种算法的折中。响应比为作业的响应时间与作业需要执行的时间之比。作业的响应时间为作业进入系统后的等待时间与作业要求处理器处理的时间之和。 -
优先权高者优先(Highest-Priority-First,HPF)调度算法
优先权高者优先调度算法与响应比高者优先调度算法十分相似,根据作业的优先权进行作业调度,每次总是选取优先权高的作业优先调度。作业的优先权通常用一个整数表示,也叫优先数。优先数的大小与优先权的关系由系统或者用户规定。优先权高者优先调度算法综合考虑了作业执行时间和等待时间的长短、作业的缓急度,作业对外部设备的使用情况等因素,根据系统设计目标和运行环境而给定各个作业的优先权,决定作业调度的先后顺序。
本实验所选用的调度算法均默认为非抢占式调度。
实验所用的测试数据如下表所示。
本实验所用的测试数据如下表所示
作业Id | 到达时间 | 执行时间 | 优先权 |
---|---|---|---|
1 | 800 | 50 | 0 |
2 | 815 | 30 | 1 |
3 | 830 | 25 | 2 |
4 | 835 | 20 | 2 |
5 | 845 | 15 | 2 |
6 | 700 | 10 | 1 |
7 | 820 | 5 | 0 |
作业的数据结构:
typedef struct node
{
int number; // 作业号
int reach_time;// 作业抵达时间
int need_time;// 作业的执行时间
int privilege;// 作业优先权
float excellent;// 响应比
int start_time;// 作业开始时间
int wait_time;// 等待时间
int visited;// 作业是否被访问过
bool isreached;// 作业是否已经抵达
}job;
重要函数说明:
void initial_jobs()
初始化所有作业信息
void reset_jinfo()
重置所有作业信息
int findminjob(job jobs[],int count)
找到执行时间最短的作业。输入参数:所有的作业信息及待查找的作业总数,输出为执行时间最短的作业id
int findrearlyjob(job jobs[],int count)
找到达到最早的作业 输入参数:所有的作业信息及待查找的作业总数,输出参数为最早达到的作业id
void readJobdata()
读取作业的基本信息
void FCFS()
先来先服务算法
void SFJschdulejob(job jobs[],int count)
短作业优先算法 输入参数:所有的作业信息及待查找的作业总数
(二)实验内容
运行程序参考代码(如下所示)
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
//最大作业数量
const int MAXJOB=50;
//作业的数据结构
typedef struct node
{
int number;//作业号
int reach_time;//作业抵达时间
int need_time;//作业的执行时间
int privilege;//作业优先权
float excellent;//响应比
int start_time;//作业开始时间
int wait_time;//等待时间
int visited;//作业是否被访问过
bool isreached;//作业是否抵达
}job;
job jobs[MAXJOB];//作业序列
int quantity;//作业数量
//初始化作业序列
void initial_jobs()
{
int i;
for(i=0;i<MAXJOB;i++)
{
jobs[i].number=0;
jobs[i].reach_time=0;
jobs[i].privilege=0;
jobs[i].excellent=0;
jobs[i].start_time=0;
jobs[i].wait_time=0;
jobs[i].visited=0;
jobs[i].isreached=false;
}
quantity=0;
}
//重置全部作业信息
void reset_jinfo()
{
int i;
for(i=0;i<MAXJOB;i++)
{
jobs[i].start_time=0;
jobs[i].wait_time=0;
jobs[i].visited=0;
}
}
//查找当前current_time已到达未执行的最短作业,若无返回-1
int findminjob(job jobs[],int count)
{
int minjob=-1;//=jobs[0].need_time;
int minloc=-1;
for(int i=0;i<count;i++)
{
if(minloc==-1){
if( jobs[i].isreached==true && jobs[i].visited==0){
minjob=jobs[i].need_time;
minloc=i;
}
}
else if(minjob>jobs[i].need_time&&jobs[i].visited==0&&jobs[i].isreached==true)
{
minjob=jobs[i].need_time;
minloc=i;
}
}
return minloc;
}
//查找最早到达作业,若全部到达返回-1.
int findrearlyjob(job jobs[],int count)
{
int rearlyloc=-1;
int rearlyjob=-1;
for(int i=0;i<count;i++)
{
if(rearlyloc==-1){
if(jobs[i].visited==0){
rearlyloc=i;
rearlyjob=jobs[i].reach_time;
}
}
else if(rearlyjob>jobs[i].reach_time&&jobs[i].visited==0)
{
rearlyjob=jobs[i].reach_time;
rearlyloc=i;
}
}
return rearlyloc;
}
//读取作业数据
void readJobdata()
{
FILE *fp;
char fname[20];
int i;
//输入测试文件文件名
printf("please input job data file name\n");
scanf("%s",fname);
if((fp=fopen(fname,"r"))==NULL)
{
printf("error, open file failed, please check filename:\n");
}
else
{
//依次读取作业信息
while(!feof(fp))
{
if(fscanf(fp,"%d %d %d %d",&jobs[quantity].number,&jobs[quantity].reach_time,&jobs[quantity].need_time,&jobs[quantity].privilege)==4)
quantity++;
}
//打印作业信息
printf("output the origin job data\n");
printf("---------------------------------------------------------------------\n");
printf("\tjobID\treachtime\tneedtime\tprivilege\n");
for(i=0;i<quantity;i++)
{ printf("\t%-8d\t%-8d\t%-8d\t%-8d\n",jobs[i].number,jobs[i].reach_time,jobs[i].need_time,jobs[i].privilege);
}
}
}
//FCFS
void FCFS()
{
int i;
int current_time=0;
int loc;
int total_waitime=0;
int total_roundtime=0;
//获取最近到达的作业
loc=findrearlyjob(jobs,quantity);
//输出作业流
printf("\n\nFCFS算法作业流\n");
printf("------------------------------------------------------------------------\n");
printf("\tjobID\treachtime\tstarttime\twaittime\troundtime\n");
current_time=jobs[loc].reach_time;
//每次循环找出最先到达的作业并打印相关信息
for(i=0;i<quantity;i++)
{
if(jobs[loc].reach_time>current_time)
{
jobs[loc].start_time=jobs[loc].reach_time;
current_time=jobs[loc].reach_time;
}
else
{
jobs[loc].start_time=current_time;
}
jobs[loc].wait_time=current_time-jobs[loc].reach_time;
printf("\t%-8d\t%-8d\t%-8d\t%-8d\t%-8d\n",loc+1,jobs[loc].reach_time,jobs[loc].start_time,jobs[loc].wait_time,
jobs[loc].wait_time+jobs[loc].need_time);
jobs[loc].visited=1;
current_time+=jobs[loc].need_time;
total_waitime+=jobs[loc].wait_time;
total_roundtime=total_roundtime+jobs[loc].wait_time+jobs[loc].need_time;
//获取剩余作业中最近到达作业
loc=findrearlyjob(jobs,quantity);
}
printf("总等待时间:%-8d 总周转时间:%-8d\n",total_waitime,total_roundtime);
printf("平均等待时间: %4.2f 平均周转时间: %4.2f\n",(float)total_waitime/(quantity),(float)total_roundtime/(quantity));
}
//短作业优先作业调度
void SFJschdulejob(job jobs[],int count)
{
}
//高响应比调度算法
void HRRFschdulejob()
{
}
//优先权高者优先调度算法
void HPF(job jobs[])
{
}
int main()
{
initial_jobs();
readJobdata();
FCFS();
reset_jinfo();
SFJschdulejob(jobs,quantity);
system("pause");
return 0;
}
要求:
1、通过程序的打印信息来检查作业信息的读入是否正确。
2、运行FCFS算法,检查其运算结果是否正确
3、根据下图所示补充短作业优先代码,并计算其等待时间和周转时间。
4、参考以上算法的实现方法,编写高响应比优先算法和优先权高者优先算法。
注:请把以上4个要求的程序实现及运行结果写在实验报告中。
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
// 最大作业数量
#define MAXJOB 50
// 作业的数据结构
typedef struct node
{
int number; // 作业号
int reach_time; // 作业抵达的时间
int need_time; // 作业的执行需要的时间
int privilege; // 作业优先级
// 以上是从文件中输入的信息
float excellent; // 作业响应比
int start_time; // 作业开始时间
int wait_time; // 作业等待时间
int visited; // 作业是否已经被访问过
} job;
// 作业序列
job jobs[MAXJOB];
// 作业数量
int quantity;
// 初始化所有作业
void initial_jobs()
{
int i;
for (i = 0; i < MAXJOB; i++)
{
jobs[i].number = 0;
jobs[i].reach_time = 0;
jobs[i].privilege = 0;
jobs[i].excellent = 0;
jobs[i].start_time = 0;
jobs[i].wait_time = 0;
jobs[i].visited = 0;
}
quantity = 0;
}
// 重置所有作业的信息
void reset_jinfo()
{
int i;
for (i = 0; i < MAXJOB; i++)
{
jobs[i].start_time = 0;
jobs[i].wait_time = 0;
jobs[i].visited = 0;
}
}
// 读取作业的基本信息
void readJobdata()
{
FILE *fp;
char fname[20];
int i;
printf("请输入作业信息文件名:\n");
scanf("%s", fname);
if ((fp = fopen(fname, "r")) == NULL)
printf("error,open file failed,please check filename:\n");
else
{
// 读取文件中的作业信息
while (!feof(fp))
{
if (fscanf(fp, "%d %d %d %d", &jobs[quantity].number, &jobs[quantity].reach_time, &jobs[quantity].need_time, &jobs[quantity].privilege) == 4)
quantity++;
}
// 打印作业信息
printf("检查作业信息的读入\n");
printf("---------------------------------\n");
printf("\t作业ID\t到达时间\t执行时间\t优先权\n");
for (i = 0; i < quantity; i++)
printf("\t%-8d\t%-8d\t%-8d\t%-8d\n", jobs[i].number, jobs[i].reach_time, jobs[i].need_time, jobs[i].privilege);
}
}
// 找出当前时间的已到达的 执行时间最短的作业
int findminjob(job jobs[], int current_time)
{
int mincost = 1000;
int minloc = -1;
// 找到当前时间已到达的且且未执行 且需要时间最小的作业
for (int i = 0; i < quantity; i++)
{
if (jobs[i].reach_time <= current_time && jobs[i].visited == 0)
{
if (jobs[i].need_time < mincost)
{
mincost = jobs[i].need_time;
minloc = i;
}
}
}
// 在当前时间未找到满足要求的作业,即无未执行的作业
if (minloc == -1)
{
// 从所有作业找到一个作业,最早到达的未执行的最短作为返回值
int early_time = 10000;
for (int i = 0; i < quantity; i++)
{
// 找到最早到达且未执行
if (jobs[i].reach_time < early_time && jobs[i].visited == 0)
{
early_time = jobs[i].reach_time;
mincost = jobs[i].need_time;
minloc = i;
}
// 找到与当前最早时间相同,且更短的作业
else if (jobs[i].reach_time == early_time && jobs[i].need_time < mincost && jobs[i].visited == 0)
{
mincost = jobs[i].need_time;
minloc = i;
}
}
}
return minloc;
}
// 找到到达最早的作业
int findearlyjob(job jobs[], int count)
{
int earlyloc = -1;
int earlyjob = -1;
for (int i = 0; i < count; i++)
{
// 找到第一个最早且未被执行过的作业
if (earlyloc == -1)
{
if (jobs[i].visited == 0)
{
earlyloc = i;
earlyjob = jobs[i].reach_time;
}
}
else if (earlyjob > jobs[i].reach_time && jobs[i].visited == 0)
{
earlyjob = jobs[i].reach_time;
earlyloc = i;
}
}
return earlyloc;
}
// 更新响应比
int updateExcellent(job jobs[], int current_time)
{
int next = -1;
int max_excellent = -1;
int i = 0;
// 设置所有已到达作业且未执行作业的响应比,因为已经按照到达时间排序,所以当循环到作业的到达时间大于当前时间后就无须处理之后的作业了,因为必定此时未到达
for (i = 0; i < quantity && jobs[i].reach_time <= current_time; i++)
{
if (jobs[i].visited == 0)
{
jobs[i].wait_time = current_time - jobs[i].reach_time;
// 计算响应比:响应时间 比 执行时间
jobs[i].excellent = 1 + (double)jobs[i].wait_time / (double)jobs[i].need_time;
// 更新最大响应比的作业
if (jobs[i].excellent > max_excellent)
{
max_excellent = jobs[i].excellent;
next = i;
}
}
}
// 若在当前时间,所有作业中没有未执行的作业
if (max_excellent == -1)
{
int early_time = 10000;
for (int i = 0; i < quantity; i++)
{
// 找到未执行的最早到达的作业,更新其响应比,因为已经按照到达时间排序,所以满足要求的第一个作业就是
if (jobs[i].reach_time < early_time && jobs[i].visited == 0)
{
early_time = jobs[i].reach_time;
next = i;
jobs[i].excellent = 1 + (double)jobs[i].wait_time / (double)jobs[i].need_time;
break;
}
}
}
return next;
}
// 先来先服务算法
void FCFS()
{
int i;
int current_time = 0;
int loc;
int total_waittime = 0;
int total_roundtime = 0;
// 获取最近到达的作业
loc = findearlyjob(jobs, quantity);
printf("\n\nFCFS算法\n");
printf("---------------------------\n");
printf("\t作业ID\t到达时间\t开始时间\t等待时间\t周转时间\n");
current_time = jobs[loc].reach_time;
// 每次循环找到最先到达的作业并打印相关信息
for (i = 0; i < quantity; i++)
{
// 如果当前获取到的最早到达的作业比当前时间还要大,设置作业开始执行的时间为作业到达的时间,重新设置当前时间为这个作业的到达时间
if (jobs[loc].reach_time > current_time)
{
jobs[loc].start_time = jobs[loc].reach_time;
current_time = jobs[loc].reach_time;
}
// 当前时间,找到的那个最早到达的作业已经到达了,直接设置开始时间为当前时间
else
jobs[loc].start_time = current_time;
// 设置进程的等待时间,为当前时间-到达时间
jobs[loc].wait_time = current_time - jobs[loc].reach_time;
// 输出信息
printf("\t%-8d\t%-8d\t%-8d\t%-8d\t%-8d\n", loc + 1, jobs[loc].reach_time, jobs[loc].start_time, jobs[loc].wait_time, jobs[loc].wait_time + jobs[loc].need_time);
// 设置已执行
jobs[loc].visited = 1;
// 当前时间更新为 +=作业执行时间
current_time += jobs[loc].need_time;
// 更新等待时间的和 与 周转时间的和
total_waittime += jobs[loc].wait_time;
total_roundtime += (jobs[loc].wait_time + jobs[loc].need_time);
// 获取剩余作业中的最早到达的作业
loc = findearlyjob(jobs, quantity);
}
printf("总等待时间:%-8d 总周转时间:%-8d\n", total_waittime, total_roundtime);
printf("平均等待时间: %4.2f 平均周转时间: %4.2f\n", (float)total_waittime / (quantity), (float)total_roundtime / (quantity));
}
// 短作业优先
void SFJschdulejob()
{
int i;
int current_time = 0;
int total_waittime = 0;
int total_roundtime = 0;
// 找到最早到达的作业
int earlyest = findearlyjob(jobs, quantity);
// 在最早的作业达到的情况下,找到此时最短的作业,当然是第一个到达的作业
int loc = findminjob(jobs, jobs[earlyest].reach_time);
printf("\n\n短作业优先算法\n");
printf("----------------------\n");
printf("\t作业ID\t到达时间\t开始时间\t等待时间\t周转时间\n");
for (i = 0; i < quantity; i++)
{
// 若当前最短的作业比当前时间还大
if (jobs[loc].reach_time > current_time)
{
// 该作业开始时间就是执行时间
jobs[loc].start_time = jobs[loc].reach_time;
current_time = jobs[loc].reach_time;
}
else
{
jobs[loc].start_time = current_time;
jobs[loc].wait_time = current_time - jobs[loc].reach_time;
}
printf("\t%-8d\t%-8d\t%-8d\t%-8d\t%-8d\n", loc + 1, jobs[loc].reach_time, jobs[loc].start_time, jobs[loc].wait_time, jobs[loc].wait_time + jobs[loc].need_time);
total_waittime += jobs[loc].wait_time;
total_roundtime += jobs[loc].wait_time + jobs[i].need_time;
current_time += jobs[loc].need_time;
jobs[loc].visited = 1;
loc = findminjob(jobs, current_time);
}
printf("总等待时间:%-8d 总周转时间:%-8d\n", total_waittime, total_roundtime);
printf("平均等待时间: %4.2f 平均周转时间: %4.2f\n", (float)total_waittime / (quantity), (float)total_roundtime / (quantity));
}
// 高响应比调度算法
void HRRFschdulejob()
{
int i, j;
job temp[MAXJOB];
// 保存副本
for (int i = 0; i < quantity; i++)
temp[i] = jobs[i];
// 对到达时间进行排序
for (i = 0; i < quantity - 1; i++)
{
for (j = 0; j < quantity - 1 - i; j++)
{
if (jobs[j].reach_time > jobs[j + 1].reach_time)
{
job temp = jobs[j];
jobs[j] = jobs[j + 1];
jobs[j + 1] = temp;
}
}
}
int current_time = 0;
int total_waitime = 0;
int total_roundtime = 0;
// 第二个参数传最早到达作业的时间为当前时间,更新所有作业的响应比,第一个执行的作业肯定是先到达的。
int loc = updateExcellent(jobs, jobs[0].reach_time);
printf("高响应比优先算法\n");
printf("------------------------------------\n");
printf("\t作业ID\t到达时间\t开始时间\t等待时间\t周转时间\n");
// 这里处理类似于前两个算法
for (i = 0; i < quantity; i++)
{
if (jobs[loc].reach_time > current_time)
{
jobs[loc].start_time = jobs[loc].reach_time;
jobs[loc].wait_time = 0;
current_time = jobs[loc].start_time + jobs[loc].need_time;
}
else
{
jobs[loc].start_time = current_time;
jobs[loc].wait_time = current_time - jobs[loc].reach_time;
current_time += jobs[loc].need_time;
}
printf("\t%-8d\t%-8d\t%-8d\t%-8d\t%-8d\n", jobs[loc].number, jobs[loc].reach_time, jobs[loc].start_time, jobs[loc].wait_time,jobs[loc].wait_time + jobs[loc].need_time);
total_waitime += jobs[loc].wait_time;
total_roundtime += jobs[loc].wait_time + jobs[loc].need_time;
jobs[loc].visited = 1;
// 更新当前时间下的未执行作业的响应比,并找到最大响应比
loc = updateExcellent(jobs, current_time);
}
printf("总等待时间:%-8d 总周转时间:%-8d\n", total_waitime, total_roundtime);
printf("平均等待时间: %4.2f 平均周转时间: %4.2f\n", (float)total_waitime / (quantity), (float)total_roundtime / (quantity));
// 还原数据
for (int i = 0; i < quantity; i++)
jobs[i] = temp[i];
}
// 优先权高者优先调度算法
void HPF()
{
int i, j;
// 按照到达时间排序
for (i = 0; i < quantity - 1; i++)
{
for (j = 0; j < quantity - 1 - i; j++)
{
if (jobs[j].reach_time >= jobs[j + 1].reach_time)
{
job temp = jobs[j];
jobs[j] = jobs[j + 1];
jobs[j + 1] = temp;
}
}
}
// 到达时间相同的情况下,排序优先级
for (i = 0; i < quantity - 1; i++)
{
for (j = 0; j < quantity - 1 - i; j++)
{
if (jobs[j].reach_time == jobs[j + 1].reach_time && jobs[j].privilege <= jobs[j + 1].privilege)
{
job temp = jobs[j];
jobs[j] = jobs[j + 1];
jobs[j + 1] = temp;
}
}
}
int current_time = 0;
int total_waitime = 0;
int total_roundtime = 0;
// 因为已经排好序,所以直接使用0位置作业,是最先到达的作业,并且是在相同时间下优先权最高的
int loc = 0;
printf("优先权高者优先算法\n");
printf("---------------------------------\n");
printf("\t作业ID\t到达时间\t开始时间\t等待时间\t周转时间\n");
for (i = 0; i < quantity; i++)
{
if (jobs[loc].reach_time > current_time)
{
jobs[loc].start_time = jobs[loc].reach_time;
current_time = jobs[loc].start_time + jobs[loc].need_time;
}
else
{
jobs[loc].start_time = current_time;
current_time += jobs[loc].need_time;
}
jobs[loc].wait_time = jobs[loc].start_time - jobs[loc].reach_time;
printf("\t%-8d\t%-8d\t%-8d\t%-8d\t%-8d\n", jobs[loc].number, jobs[loc].reach_time, jobs[loc].start_time, jobs[loc].wait_time,jobs[loc].wait_time + jobs[loc].need_time);
total_waitime += jobs[loc].wait_time;
total_roundtime += jobs[loc].wait_time + jobs[loc].need_time;
jobs[loc].visited = 1;
// 以上操作与前几个算法相似
// 下面开始寻找已到达的优先权最高的作业
int next = -1;
int max_privilege = -1;
// 因为已经按照到达时间排序,所以当前时间小于到达时间的作业及以后的作业必定未到达,不用再处理了
for (j = 0; j < quantity && current_time >= jobs[j].reach_time; j++)
{
// 找到未执行且优先权最大的作业
if (jobs[j].visited == 0 && jobs[j].privilege > max_privilege)
{
max_privilege = jobs[j].privilege;
next = j;
}
}
// 没有找到满足要求的作业的话,直接执行下一个到达的作业
if (next == -1)
{
next = loc + 1;
}
loc = next;
}
printf("总等待时间:%-8d 总周转时间:%-8d\n", total_waitime, total_roundtime);
printf("平均等待时间: %4.2f 平均周转时间: %4.2f\n", (float)total_waitime / (quantity), (float)total_roundtime / (quantity));
}
int main()
{
initial_jobs();
readJobdata();
FCFS();
reset_jinfo();
SFJschdulejob();
reset_jinfo();
HRRFschdulejob();
reset_jinfo();
HPF();
reset_jinfo();
system("pause");
return 0;
}
四、实验总结
由四种算法的测试数据来看,算法思想不同,所需的等待时间和周转时间也不同。
作业调度算法 | 等待时间 | 执行时间 | 优先权 |
---|---|---|---|
FCFS | √ | ||
SJF | √ | ||
HRRF | √ | √ | |
HPF | √ |
由表得出FCFS算法仅考虑作业的等待时间,等待时间长的优先考虑;SJF算法主要考虑作业的执行时间,执行时间短的优先考虑;HRRF算法同时考虑了作业的等待时间和执行时间,是FCFS和SJF算法的折中;HPF算法仅考虑作业的优先权,优先权高者先执行。
我们实验结果中可以发现对测试数据而言,并非HRRF算法的平均等待时间和平均周转时间最短。对于这组作业,SJF算法的平均等待时间和平均周转时间比 HRRF算法和HPF算法的短,说明最适合这个作业的调度算法是SJF。
由此可以得出判断算法的好坏要根据具体的作业,如果对于a作业A算法的平均等待时间和周转时间是最短的,那说明A算法是最适合a作业的调度算法。
请总结一下本次实验的收获、教训和感受,结合课本内容谈一下你对操作系统中各种作业调度算法优缺点的理解。
FCFS (First-Come, First-Serve)
优点:
- 简单易懂,易于实现。
- 对于长作业比较有利,因为它们不会被其他作业频繁打断。
- 适用于批处理系统,因为批处理系统通常没有交互性要求。
缺点:
- 不利于短作业,它们可能需要等待很长时间才能得到执行。
- 不利于I/O繁忙型作业,因为它们在I/O操作时会释放CPU,但FCFS算法不会重新调度它们。
- 不适用于分时系统,因为分时系统需要确保所有用户都能得到快速的响应。
SJF (Shortest Job First)
优点:
- 照顾了短进程,减少了平均等待时间和平均周转时间。
- 提高了系统的吞吐量。
缺点:
- 对长进程不利,可能导致饥饿现象。
- 进程的运行时间很难精确估计,特别是在实际环境中。
- 未考虑进程的紧迫程度。
- 可能需要额外的数据结构来跟踪和比较进程长度,增加了系统开销。
HRRF (Highest Response Ratio Next)
优点:
- 既考虑了作业长度(通过周转时间),又考虑了等待时间(通过响应比),从而既照顾了短作业又照顾了长作业。
- 同时考虑了先到达进程。
缺点:
- 调度之前需要计算各个进程的响应比,增加了系统开销。
- 可能导致计算响应比时产生浮点数运算,增加了复杂性。
- 对实时进程的反应可能不够及时。
HPF (Highest Priority First)
优点:
- 调度灵活,可以根据不同的调度需求设置不同的优先级。
- 可以适应多种应用场景,如操作系统内核任务、交互式任务等。
缺点:
- 进程优先级的划分和确定每个进程优先级比较困难。优先级设置不当可能导致系统性能下降。
- 可能导致优先级反转问题,即低优先级的进程长时间占用CPU,而高优先级的进程无法获得执行。
- 可能导致饥饿现象,特别是当某些进程的优先级总是低于其他进程时。
- 可能需要额外的数据结构来跟踪和比较进程优先级,增加了系统开销。