老师布置的实习题目如下:
设计目的:
加深对请求磁盘调度管理实现原理的理解,掌握磁盘调度算法。
设计内容:
通过编程实现不同磁盘调度算法。
设定开始磁道号寻道范围,依据起始扫描磁道号和最大磁道号数,随机产生要进行寻道的磁道号序列。选择磁盘调度算法,显示该算法的磁道访问顺序,计算出移动的磁道总数和平均寻道总数。
常用的磁盘调度算法简介如下,请在以下算法中任意选择两种实现,并对算法性能进行分析对比。
1. 最短寻道优先算法SSTF:该算法选择这样的进程:其要求访问的磁道与当前磁头所在的磁道距离最近,以使每次的寻道时间最短。
2. 扫描算法SCAN:该算法不仅考虑到欲访问的磁道与当前磁道间的距离,更优先考虑的是磁头当前的移动方向。例如,当磁头正在自里向外移动时,SCAN算法所考虑的下一个访问对象,应是其欲访问的磁道既在当前磁道之外,又是距离最近的。这样自里向外地访问,直至再无更外的磁道需要访问时,才将磁臂换向为自外向里移动。
3.循环扫描算法CSCAN:CSCAN算法规定磁头单向移动,例如,只是自里向外移动,当磁头移到最外的磁道并访问后,磁头立即返回到最里的欲访问的磁道,亦即将最小磁道号紧接着最大磁道号构成循环,进行循环扫描。
代码如下:
import java.util.Scanner;
import java.util.Arrays;
class Cipandiaodu{
public static void main(String[] args){
/*
要用到的几种算法分别是
冒泡排序算法
先来先服务调度算法
最短寻道时间优先调度算法
扫描调度算法
循环扫描调度算法
*/
Cipandiaodu A=new Cipandiaodu();
int a;
int now;
int c;
int[] cidao=new int[1000];
int i=0,count;
int[] str=new int[100];
System.out.println("随机产生一个磁道序列(包含10个磁道)\n");
for(i=0;i<10;i++){
str[i]=(int)(Math.random()*200);
cidao[i]=str[i];
}
count=i-1;
System.out.println("得到的磁道序列为:");
for(i=0;i<count;i++)
{
System.out.print(cidao[i]+" ");
}
System.out.println();
while(true)
{
System.out.println();
System.out.println("----------------------------------------------");System.out.println("------ 系统菜单 ------");
System.out.println("--- ---");
System.out.println("-- 1. 先来先服务 --");
System.out.println("-- 2. 最短寻道时间优先 --");
System.out.println("-- 3. 扫描调度 --");
System.out.println("-- 4. 循环扫描 --");
System.out.println("-- 5. 退出 --");
System.out.print("请选择算法:");
Scanner w=new Scanner(System.in);
c=w.nextInt();
if(c==5)
break;
switch(c)
{
case 1: //使用FCFS算法
A.FCFS(cidao,count);
break;
case 2: //使用SSTF算法
A.SSTF(cidao,count);
break;
case 3: //使用SCAN算法
A.SCAN(cidao,count);
break;
case 4: //使用CSCAN算法
A.CSCAN(cidao,count);
break;
}
}
}
void FCFS(int cidao[],int m) //磁道号数组,个数为m
{
int now;//当前磁道号
int sum=0; //总寻道长度
int j,i;
int a;
float ave=0; //平均寻道长度
System.out.println("磁盘请求序列为:");
for( i=0;i<m;i++) //按先来先服务的策略输出磁盘请求序列
{
System.out.print(cidao[i]+" ");
}
System.out.println();
System.out.print("请输入当前的磁道号:");
Scanner w=new Scanner(System.in);
now=w.nextInt();
sum+=Math.abs(cidao[0]-now);
System.out.println("磁盘扫描序列为:");
for( i=0;i<m;i++) //输出磁盘扫描序列
{
System.out.print(cidao[i]+" ");
}
for(i=0,j=1;j<m;i++,j++) //求平均寻道长度
{
sum+=Math.abs(cidao[j]-cidao[i]);
ave=(float)sum/m;
}
System.out.println();
System.out.println("平均寻道长度:"+ave);
}
void SSTF(int cidao[],int m)
{
int k=1;
int now,l,r;
int i,j,sum=0;
int a;
float ave;
Arrays.sort(cidao);
System.out.print("请输入当前的磁道号:");
Scanner w=new Scanner(System.in);
now=w.nextInt();
if(cidao[m-1]<=now) //若当前磁道号大于请求序列中最大者,则直接由外向内依次给予各请求服务
{
System.out.println("磁盘扫描序列为:");
for(i=m-1;i>=0;i--)
System.out.print(cidao[i]+" ");
sum=now-cidao[0];
}
if(cidao[0]>=now) //若当前磁道号小于请求序列中最小者,则直接由内向外依次给予各请求服务
{
System.out.println("磁盘扫描序列为:");
for(i=0;i<m;i++)
System.out.print(cidao[i]+" ");
sum=cidao[m-1]-now;
}
if(now>cidao[0]&&now<cidao[m-1]) //若当前磁道号大于请求序列中最小者且小于最大者
{
System.out.println("磁盘扫描序列为:");
while(cidao[k]<now) //确定当前磁道在已排的序列中的位置,后面的算法都用到了,可以直接复制后少量修改,节省时间。
{
k++;
}
l=k-1;
r=k;
while((l>=0)&&(r<m)) //当前磁道在请求序列范围内
{
if((now-cidao[l])<=(cidao[r]-now)) //选择与当前磁道最近的请求给予服务
{
System.out.print(cidao[l]+" ");
sum+=now-cidao[l];
now=cidao[l];
l=l-1;
}
else
{
System.out.print(cidao[r]+" ");
sum+=cidao[r]-now;
now=cidao[r];
r=r+1;
}
}
if(l==-1) //磁头移动到序列的最小号,返回外侧扫描仍未扫描的磁道
{
for(j=r;j<m;j++)
{
System.out.print(cidao[j]+" ");
}
sum+=cidao[m-1]-cidao[0];
}
else //磁头移动到序列的最大号,返回内侧扫描仍未扫描的磁道
{
for(j=l;j>=0;j--)
{
System.out.print(cidao[j]+" ");
}
sum+=cidao[m-1]-cidao[0];
}
}
ave=(float)(sum)/(float)(m);
System.out.println();
System.out.println("平均寻道长度: "+ave);
}
void SCAN(int cidao[],int m) //先要给出当前磁道号和移动臂的移动方向
{
int k=1;
int now,l,r,d;
int i,j,sum=0;
int a;
float ave;
Arrays.sort(cidao);
System.out.print("请输入当前的磁道号:");
Scanner w=new Scanner(System.in);
now=w.nextInt();
if(cidao[m-1]<=now) //若当前磁道号大于请求序列中最大者,则直接由外向内依次给予各请求服务,此情况同最短寻道优先
{
System.out.println("磁盘扫描序列为:");
for(i=m-1;i>=0;i--)
System.out.print(cidao[i]+" ");
sum=now-cidao[0];
}
if(cidao[0]>=now) //若当前磁道号小于请求序列中最小者,则直接由内向外依次给予各请求服务,此情况同最短寻道优先
{
System.out.println("磁盘扫描序列为:");
for(i=0;i<m;i++)
System.out.print(cidao[i]+" ");
sum=cidao[m-1]-now;
}
if(now>cidao[0]&&now<cidao[m-1]) //若当前磁道号大于请求序列中最小者且小于最大者
{
while(cidao[k]<now)
{
k++;
}
l=k-1;
r=k;
System.out.println("请输入当前移动臂的移动的方向 (1 表示向外 ,0表示向内) : ");
Scanner x=new Scanner(System.in);
d=x.nextInt();
if(d==0) //选择移动臂方向向内,则先向内扫描
{
System.out.println("磁盘扫描序列为:");
for(j=l;j>=0;j--)
{
System.out.print(cidao[j]+" ");
}
for(j=r;j<m;j++) //磁头移动到最小号,则改变方向向外扫描未扫描的磁道
{
System.out.print(cidao[j]+" ");
}
sum=now-2*cidao[0]+cidao[m-1];
}
else //选择移动臂方向向外,则先向外扫描
{
System.out.println("磁盘扫描序列为:");
for(j=r;j<m;j++)
{
System.out.print(cidao[j]+" ");
}
for(j=l;j>=0;j--) //磁头移动到最大号,则改变方向向内扫描未扫描的磁道
{
System.out.print(cidao[j]+" ");
}
sum=-now-cidao[0]+2*cidao[m-1];
}
}
ave=(float)(sum)/(float)(m);
System.out.println();
System.out.print("平均寻道长度: ");
}
void CSCAN(int cidao[],int m)
{
int k=1;
int now,l,r;
int i,j,sum=0;
int a;
float ave;
Arrays.sort(cidao);
System.out.print("请输入当前的磁道号:");
Scanner w=new Scanner(System.in);
now=w.nextInt();
if(cidao[m-1]<=now) //若当前磁道号大于请求序列中最大者,则直接将移动臂移动到最小号磁道依次向外给予各请求服务
{
System.out.println("磁盘扫描序列为:");
for(i=0;i<m;i++)
System.out.print(cidao[i]+" ");
sum=now-2*cidao[0]+cidao[m-1];
}
if(cidao[0]>=now) //若当前磁道号小于请求序列中最小者,则直接由内向外依次给予各请求服务,此情况同最短寻道优先
{
System.out.println("磁盘扫描序列为:");
for(i=0;i<m;i++)
System.out.print(cidao[i]+" ");
sum=cidao[m-1]-now;
}
if(now>cidao[0]&&now<cidao[m-1]) //若当前磁道号大于请求序列中最小者且小于最大者
{
System.out.println("磁盘扫描序列为:");
while(cidao[k]<now) //单向反复地从内向外扫描
{
k++;
}
l=k-1;
r=k;
for(j=r;j<m;j++)
{
System.out.print(cidao[j]+" ");
}
for(j=0;j<r;j++) //当扫描完最大号磁道,磁头直接移动到最小号磁道,再向外扫描未扫描的磁道
{
System.out.print(cidao[j]+" ");
}
sum=2*cidao[m-1]+cidao[l]-now-2*cidao[0];
}
ave=(float)(sum)/(float)(m);
System.out.println();
System.out.println("平均寻道长度: ");
}
}
如有不对,欢迎指出。