1、实验目的
(1) 了解磁盘结构以及磁盘上数据的组织方式。 (2) 掌握磁盘访问时间的计算方式。 (3) 掌握常用磁盘调度算法及其相关特性。
2、实验基本知识及原理
(1)磁盘数据的组织 磁盘上每一条物理记录都有唯一的地址,该地址包括三个部分:磁头号(盘面号)、柱面号(磁 道号)和扇区号。给定这三个量就可以唯一地确定一个地址。 (2)磁盘访问时间的计算方式 磁盘在工作时以恒定的速率旋转。为保证读或写,磁头必须移动到所要求的磁道上,当所要求 的扇区的开始位置旋转到磁头下时,开始读或写数据。对磁盘的访问时间包括:寻道时间、旋转延 迟时间和传输时间。
(3)磁盘调度算法 磁盘调度的目的是要尽可能降低磁盘的寻道时间,以提高磁盘 I/O 系统的性能。 先进先出算法:按访问请求到达的先后次序进行调度。 最短服务时间优先算法:优先选择使磁头臂从当前位置开始移动最少的磁盘 I/O 请求进行调度。 SCAN(电梯算法):要求磁头臂先沿一个方向移动,并在途中满足所有未完成的请求,直到它 到达这个方向上的最后一个磁道,或者在这个方向上没有别的请求为止,后一种改进有时候称作 LOOK 策略。然后倒转服务方向,沿相反方向扫描,同样按顺序完成所有请求。 C-SCAN(循环扫描)算法:在磁盘调度时,把扫描限定在一个方向,当沿某个方向访问到最 后一个磁道时,磁头臂返回到磁盘的另一端,并再次开始扫描。
3、实验内容
本实验通过编程模拟实现几种常见的磁盘调度算法。
(1)测试数据:参见教材 P305-306,测试结果参见表 11.2。
(2)使用 C 语言编程实现 FIFO、SSTF、SCAN、C-SCAN 算法。参考代码如下:
4、代码
#include <iostream>
#include <string>
#include <iomanip>
#include<math.h>
#include <algorithm>
using namespace std;
#define MAX 999999 //最大值
#define max_length 100 //存储长度
int begin_local=0; //当前位置
int length=0; //长度
int Node[max_length]= {0}; //存储信息
int Changed_Node[max_length]= {0}; //生成的数据
//大小判断函数
bool cmp(int a,int b)//int为数组数据类型
{
return a<b;//降序排列
}
//输出函数
void OUTPUT(string Algorithm_Name)
{
int All_length=0;
cout<<Algorithm_Name<<"算法:"<<endl;
cout<<"----------------------------------------------------------------"<<endl;
//服务序列
cout<<" 服务序列: ";
for( int i=0; i<=length; i++ ) cout << Changed_Node[i] <<"\t" ;
cout<<endl;
//单次移动距离
cout<<" 移动距离: ";
for( int i=0,temp=begin_local; i<=length; i++ )
{
cout << abs(Changed_Node[i]-temp) <<"\t" ;
All_length+=abs(Changed_Node[i]-temp);
temp= Changed_Node[i];
}
cout<<endl;
//移动的距离与平均记录
cout<<" 移动的总距离:"<<All_length<<endl;
printf(" 平均寻道长度:%.3f\n", (double)All_length/length);
cout<<"----------------------------------------------------------------\n"<<endl;
}
void FIFO() //先进先出
{
Changed_Node[0]=begin_local;
for (int i=0; i<length ; i++ ) Changed_Node[i+1]=Node[i];
OUTPUT("先进先出");
}
void SSTF() //最短服务时间优先
{
int Tag[max_length]= {0},temp=MAX,Now=0;
Changed_Node[0]=begin_local;//初始位置
for (int i=1; i<=length; i++)
{
for (int j=0,temp=MAX; j<length; j++ )
{//查找最小的值
if(abs(Node[j]-Changed_Node[i-1])<=temp&&Tag[j]==0)
{
Now=j;
temp=abs(Node[j]-Changed_Node[i-1]);
}
}
Changed_Node[i]=Node[Now];
Tag[Now]=1;//标记
}
OUTPUT("最短服务时间优先");
}
void SCAN() //SCAN扫描
{
int CopyNode[max_length]= {0},temp=1;
memcpy(CopyNode,Node,length*sizeof(int));//复制数组
sort(CopyNode,CopyNode+length,cmp); //排序数组
Changed_Node[0]=begin_local; //初始位置
for (int i=0; i<length ; i++ ) //正向扫描
{
if(CopyNode[i]>=begin_local) Changed_Node[temp++]=CopyNode[i];
}
for (int i=length-1; i>=0; i-- ) //反向扫描
{
if(CopyNode[i]<=begin_local) Changed_Node[temp++]=CopyNode[i];
}
OUTPUT("SCAN扫描算法");
}
void C_SCAN() //循环扫描
{
int CopyNode[max_length]= {0},temp=1;
memcpy(CopyNode,Node,length*sizeof(int)); //复制数组
sort(CopyNode,CopyNode+length,cmp); //排序数组
Changed_Node[0]=begin_local; //初始位置
for (int i=0; i<length ; i++ )//正向扫描1
{
if(CopyNode[i]>=begin_local) Changed_Node[temp++]=CopyNode[i];
}
for (int i=0; i<length ; i++ )//正向扫描2
{
if(CopyNode[i]<=begin_local) Changed_Node[temp++]=CopyNode[i];
}
OUTPUT("C_SCAN循环扫描");
}
void INPUT()
{
printf("\n请输入调度磁道数量: ");
scanf("%d",&length);
printf("请输入磁道调度序列: ");
for(int i=0; i<length; i++) scanf("%d",&Node[i]);
printf("请输入当前的磁道号: ");
scanf("%d",&begin_local);
cout<<endl;
}
int main()
{
INPUT(); //输入数据
FIFO(); //先进先出
SSTF(); //最短时间
SCAN(); //扫描
C_SCAN(); //单向扫描
return 0;
}
5、结果图