头歌实验七 磁盘调度算法
任务描述
本关任务:编写程序用三种算法选择磁道访问序列。
相关知识
为了完成本关任务,你需要掌握:1.理解磁盘磁道调度算法,2.编写程序实现对磁道的选择。
磁道的调度
磁盘是计算机中重要的存储设备,温切斯特是一种典型的盘片式硬盘,这种设备有若干个盘片,盘片具有存储面,盘面划分成多个同心环作为磁道,磁道被划分成若干个扇区。进行读写数据时磁关须移动到指定的磁道上,磁头移动到磁道上经历的时间是寻道时间,多个进程访问磁盘希望能够使磁盘的平均寻道时间最小,本实验模拟了这些算法的实现。 磁盘的读写是通过磁头的移动和盘片的旋转完成的,磁盘的访问时间有三部分:寻道时间、旋转延迟时间、传输时间。在访问时间中,寻道时间和旋转延迟时间在访问时间中占据比例较大,而旋转延迟属固定的物理特性,寻道时间则由根据算法有不同的结果。
算法介绍
常用的磁盘调度算法有先来先服务、最短寻道时间优先、扫描算法。每种算法产生一个磁头访问的磁道序列,得到一个总磁头移动数和相应的平均移动道数。
先来先服务算法FCFS
先来先服务根据进程请求访问磁盘先后次序进行调度,它对各进程公平、简单,不会出现某一进程长期得不到满足的情况。先来先服务的访问序列就是初始请求队列,无需额外进行排序,只需计算其总磁道数即可。
扫描算法SCAN
扫描算法是一种比较公平的磁道访问算法,也称为电梯算法,该算法是在磁头移动方向上走到尽头再折返访问。
最短寻道优先算法SSTF
最短寻道优先算法要求下一个要访问的磁道序号与当前磁头距离最近,该算法根据当前磁头位置决定下个访问磁道序号,因此算法有可能走往复的路程,而在持续的磁头移动过程中,新的磁头访问序列添加到队列中,较远的磁道可能一直到不到访问。所以该算法得到的寻道值可能不是全局最短。
编程要求
1、为了简化,以数组的形式表示到来的作业。 2、在调度过程中,没有考虑新增的作业,即新到来的作业。 3、手工对作业任务进行了排序。
测试说明
假定当前读写头在 90 号,给定下面的一组磁道访问序列进行调度,磁头向磁道号增加的方向移动,磁道序列保存在一个整数数组中。 30,50 ,100,180,20,90,150,70,80,10,160 为简化输入和数据处理,排序后的磁道序列保存在全局数组中, 10,20,30,50,70,80,90,100,150,160,180 平台会对你编写的代码进行测试,程序无用户输入,输出依次是SCAN,FCFS,SSTF算法中磁头移动的总磁道数。
测试输入:无 预期输出:SCAN:260,FCFS:810,SSTF:270
代码展示
//stu001.c 磁盘调度算法,程序模板,由学生完成缺失代码
//输出:SCAN:260,FCFS:810,SSTF:270
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
const int StartPos=90;
int YuanShiSeq[]={30,50,100,180,20,90,150,70,80,10,160}; //11个元素
int PaiXuSeq[] ={10,20,30,50,70,80,90,100,150,160,180}; //11个元素
int SCAN()
{ //扫描算法
int totaltracks=0;
int curNum=StartPos;
//请在begin end语句间补全程序语句实现扫描算法,算出总访问磁道数存入totaltracks变量
/* begin ************************************************************** */
//使用已经排好序的数组,可以简化计算
// 找到开始位置的索引
int direction = 1;
int startIndex = 0;
while (PaiXuSeq[startIndex] < StartPos && startIndex < 11)
{
startIndex++;
}
// 先扫描右边
for (int i = startIndex; i < 11; i++)
{
totaltracks += abs(curNum - PaiXuSeq[i]);
curNum = PaiXuSeq[i];
}
// 再扫描左边
for (int i = startIndex - 1; i >= 0; i--)
{
totaltracks += abs(curNum - PaiXuSeq[i]);
curNum = PaiXuSeq[i];
}
/* end ************************************************************** */
//程序输出总访问磁道数
return totaltracks;
}
int FCFS()
{ //先来先服务
int totaltracks=0;
int curNum=StartPos;
//请在begin end语句间补全程序语句实现FCFS算法,算出总访问磁道数存入totaltracks变量
/* begin ************************************************************** */
for (int i = 0; i < 11; i++)
{
totaltracks += abs(curNum - YuanShiSeq[i]);
curNum = YuanShiSeq[i];
}
/* end ************************************************************** */
return totaltracks;
}
int SSTF()
{ //最短寻道优先
int totaltracks=0;
int curNum=StartPos;
int i=0;
//假设当前curNum磁道大于所有的作业的当前磁道
//即curNum>PaiXuSeq[10]
int little=10,big=11;
//找出curNum磁道在PaiXuSeq[little]<=curNum<PaiXuSeq[big]的位置
//curNum磁道与左右相等的情况下,优先磁道大的方向。如果优先磁道小的方向,最短寻道时间会不一样。
//请在begin end语句间补全程序语句最短寻道优先算法,算出总访问磁道数存入totaltracks变量
/* begin ************************************************************** */
int visited[11] = {0};
for (int i = 0; i < 11; ++i)
{
int minDistance = INT_MAX;
int minIndex = -1;
for (int j = 0; j < 11; ++j)
{
if (!visited[j])
{
int distance = abs(curNum - YuanShiSeq[j]); // 使用 YuanShiSeq
if (distance < minDistance)
{
minDistance = distance;
minIndex = j;
}
}
}
// 标记为已访问
visited[minIndex] = 1;
// 更新总磁道数
totaltracks += minDistance;
curNum = YuanShiSeq[minIndex]; // 使用 YuanShiSeq
}
/* end ************************************************************** */
return totaltracks;
}
int main()
{
//为方便在线结果测试直接输出总磁道数
printf("SCAN:%d,FCFS:%d,SSTF:%d",SCAN(),FCFS(),SSTF());
return 0;
}
输出结果
SCAN:260,FCFS:810,SSTF:270