算法简介
(1)先来先服务算法(FCFS):这种算法将对磁盘的IO请求进行排队,按照先后顺序依次调度磁头。这种算法的特点是简单,合理,但没有减少寻道时间
(2)最短寻道时间算法(SSFT):这种算法优先执行所需读写的磁道离当前磁头最近的请求。这保证了平均寻道时间的最短,但缺点显而易见:离当前磁头比较远的寻道请求有可能一直得不到执行,这也就是所谓的“饥饿现象”。
(3)扫描算法(SCAN):这种算法在磁头的移动方向上选择离当前磁头所在磁道最近的请求作为下一次服务对象,这种改进有效避免了饥饿现象,并且减少了寻道时间。但缺点依然存在,那就是不利于最远一端的磁道访问请求。
(4)循环扫描算法(CSCAN):这种算法的磁头只能从最里磁道到磁盘最外层磁道。然后再由最外层磁道移动到最里层磁道,磁头是单向移动的,在此基础上,才执行和最短寻道时间算法一样的,离当前磁头最近的寻道请求。这种算法改善了SCAN算法,消除了对两端磁道请求的不公平。
- 算法模拟要求
1)给定磁盘访问请求序列,模拟实现先来先服务、寻道时间最短优先、扫描、循环扫描等磁盘调度算法;
(2)输出每种磁盘调度算法下的磁盘访问的移动顺序、每次磁头的移动距离、平均寻道长度;
- 代码模拟实现
#include<bits/stdc++.h>
using namespace std;
int a[9]={55,58,39,18,90,160,150,38,184};
int total_length[4]={0};//总寻道长度
float average[4];//平均寻道长度
int current=100;//从第100道开始处理
struct result
{
int next;//下一个被访问磁道
int number;//移动磁道数
}fcfs[9],sstf[9],scan[9],cscan[9];
void fcfs_func()//先来先服务算法
{
int i;
fcfs[0].next=a[0];
fcfs[0].number=abs(a[0]-current);//取相减的绝对值
for(i=1;i<9;i++)
{
fcfs[i].next=a[i];
fcfs[i].number=abs(a[i]-a[i-1]);
}
for(i=0;i<9;i++)//计算总寻道长度
{
total_length[0]+=fcfs[i].number;
}
average[0]=(float)total_length[0]/9;//计算平均寻道长度
}
void sstf_func()//最短寻道时间最优算法
{
int sstf_current=current;//从第current开始(100)
int temp=1000;
int index;
int visit[9]={0};//访问数组 0表示未访问过,1表示访问过
for(int i=0;i<9;i++)
{
temp=1000;
for(int j=0;j<9;j++)
{
if(abs(a[j]-sstf_current)<temp&&visit[j]==0)//找到离磁头最小的磁道
{
temp=abs(a[j]-sstf_current);
index=j;
}
}
sstf[i].next=a[index];
sstf[i].number=abs(a[index]-sstf_current);
visit[index]=1;
total_length[1]+=abs(a[index]-sstf_current);//总寻道长度
sstf_current=a[index];//当前磁头位置转移到离上一磁头最近的磁道
}
average[1]=(float)total_length[1]/9;
}
void scan_func()//扫描算法
{
int scan_current=current;//保存磁道开始的地方
int scan_arr[9];//临时数组,保存磁道请求顺序
int i,j;
for(i=0;i<9;i++)
{
scan_arr[i]=a[i];
}
sort(scan_arr,scan_arr+9);//从小到大排
j=0;
int temp=scan_current;
for(i=0;i<9;i++)
{
if(scan_arr[i]>=current)//沿磁道号增大的顺序移动
{
scan[j].next=scan_arr[i];
scan[j].number=abs(scan_arr[i]-scan_current);
scan_current=scan_arr[i];
j++;
}
}
for(i=8;i>=0;i--)
{
if(scan_arr[i]<current)//沿磁道号小的顺序移动
{
scan[j].next=scan_arr[i];
scan[j].number=abs(scan_arr[i]-scan_current);
scan_current=scan_arr[i];
j++;
}
}
for(i=0;i<9;i++)//计算总寻道长度
{
total_length[2]+=scan[i].number;
}
average[2]=(float)total_length[2]/9;//计算平均寻道长度
}
void cscan_func()//循环扫描算法
{
int cscan_current=current;//从第current开始(100)
int b[9],first_value,first_index;
int b_first_index,counts=0;
int temp=1000;
copy(a,a+9,b);//把数组a复制到b中
sort(b,b+9);
for(int i=0;i<9;i++)
{
if(cscan_current<=a[i]&&abs(a[i]-cscan_current)<temp)//找到 从里向外方向中离当前磁道最近的磁道
{
temp=abs(a[i]-cscan_current);
first_value=a[i];
first_index=i;
}
}
for(int i=0;i<9;i++)//在数组b中找到a[first_index]的位置
{
if(b[i]==first_value)
{
b_first_index=i;
break;
}
}
for(int i=b_first_index;i<9;i++,counts++)//从里向外扫描
{
cscan[counts].next=b[i];
cscan[counts].number=abs(b[i]-cscan_current);
cscan_current=b[i];
}
for(int i=0;i<b_first_index;i++,counts++)//从最里面要访问的磁道开始
{
cscan[counts].next=b[i];
cscan[counts].number=abs(b[i]-cscan_current);
cscan_current=b[i];
}
for(int i=0;i<9;i++)//计算总寻道长度
{
total_length[3]+=cscan[i].number;
}
average[3]=(float)total_length[3]/9;//计算平均寻道长度
}
void output()
{
printf(" 磁盘调度算法 \n");
printf("---------------------------------------------------------------------------------------------------------\n");
printf(" (a)FCFS (b)SSTF (c)SCAN (d)C-SCAN \n");
printf("---------------------------------------------------------------------------------------------------------\n");
printf("下一个被 移动的 下一个被 移动的 下一个被 移动的 下一个被 移动的\n");
printf("访问磁道 磁道数 访问磁道 磁道数 访问磁道 磁道数 访问磁道 磁道数\n");
printf("---------------------------------------------------------------------------------------------------------\n");
for(int i=0;i<9;i++)
printf(" %d %d %d %d %d %d %d %d\n",fcfs[i].next,fcfs[i].number,sstf[i].next,sstf[i].number,scan[i].next,scan[i].number,cscan[i].next,cscan[i].number);
cout<<endl;
printf("平均寻道长度:%2f %2f %2f %2f\n",average[0],average[1],average[2],average[3]);
}
int main()
{
fcfs_func();
sstf_func();
scan_func();
cscan_func();
output();
return 0;
}
- 运行结果