设计五:磁盘调度管理
设计目的:
加深对请求磁盘调度管理实现原理的理解,掌握磁盘调度算法。
设计内容:
通过编程实现不同磁盘调度算法。
设定开始磁道号寻道范围,依据起始扫描磁道号和最大磁道号数,随机产生要进行寻道的磁道号序列。选择磁盘调度算法,显示该算法的磁道访问顺序,计算出移动的磁道总数和平均寻道总数。
常用的磁盘调度算法简介如下,请在以下算法中任意选择两种实现,并对算法性能进行分析对比。
1. 最短寻道优先算法SSTF:该算法选择这样的进程:其要求访问的磁道与当前磁头所在的磁道距离最近,以使每次的寻道时间最短。
2. 扫描算法SCAN:该算法不仅考虑到欲访问的磁道与当前磁道间的距离,更优先考虑的是磁头当前的移动方向。例如,当磁头正在自里向外移动时,SCAN算法所考虑的下一个访问对象,应是其欲访问的磁道既在当前磁道之外,又是距离最近的。这样自里向外地访问,直至再无更外的磁道需要访问时,才将磁臂换向为自外向里移动。
3.循环扫描算法CSCAN:CSCAN算法规定磁头单向移动,例如,只是自里向外移动,当磁头移到最外的磁道并访问后,磁头立即返回到最里的欲访问的磁道,亦即将最小磁道号紧接着最大磁道号构成循环,进行循环扫描。
代码如下:
import java.util.Scanner;
import java.util.Arrays;
import java.util.Random;
class Cipandiaodu{
public static void main(String[] args){
/*
要用到的几种算法分别是
最短寻道时间优先调度算法
循环扫描调度算法
*/
Scanner reader=new Scanner(System.in);
System.out.println("请输入算法:1、最短寻道时间优先调度算法 2、循环扫描调度算法");
int input=reader.nextInt();
switch(input){
case 1:
SSTF hhh = new SSTF();
hhh.way();
break;
case 2:
CSCAN hh = new CSCAN();
hh.way();
break;
default:
System.out.println("非法输入");
break;
}
}
}
class SSTF{
void way(){
int k=1;
int now,l,r;
int i,j,sum=0;
float ave;
int num;
Scanner input = new Scanner(System.in);
System.out.println("请输入磁道数:");
num = input.nextInt();
int[] cidao=new int[num];
Random rand = new Random();
for(i = 0; i < num; i++) {
cidao[i] = rand.nextInt(200) + 1 ;
}
System.out.print("磁道序列为:");
for(i = 0; i < num; i++) {
System.out.print(cidao[i]+" ");
}
System.out.println();
Arrays.sort(cidao);
System.out.print("请输入当前的磁道号:");
Scanner w=new Scanner(System.in);
now = w.nextInt();
if(cidao[num-1]<=now) //若当前磁道号大于请求序列中最大者,则直接由外向内依次给予各请求服务
{
System.out.println("磁盘扫描序列为:");
for(i=num-1;i>=0;i--)
System.out.print(cidao[i]+" ");
sum=now-cidao[0];
}
if(cidao[0]>=now) //若当前磁道号小于请求序列中最小者,则直接由内向外依次给予各请求服务
{
System.out.println("磁盘扫描序列为:");
for(i=0;i<num;i++)
System.out.print(cidao[i]+" ");
sum=cidao[num-1]-now;
}
if(now>cidao[0]&&now<cidao[num-1]) //若当前磁道号大于请求序列中最小者且小于最大者
{
System.out.println("磁盘扫描序列为:");
while(cidao[k]<now) //确定当前磁道在已排的序列中的位置
{
k++;
}
l=k-1;
r=k;
while((l>=0)&&(r<num)) //当前磁道在请求序列范围内
{
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<num;j++)
{
System.out.print(cidao[j]+" ");
}
sum+=cidao[num-1]-cidao[0];
}
else //磁头移动到序列的最大号,返回内侧扫描仍未扫描的磁道
{
for(j=l;j>=0;j--)
{
System.out.print(cidao[j]+" ");
}
sum+=cidao[num-1]-cidao[0];
}
}
ave=(float)(sum)/(float)(num);
System.out.println();
System.out.println("平均寻道长度: "+ave);
}
}
class CSCAN{
void way(){
int k=1;
int now,l,r;
int i,j,sum=0;
int a;
float ave;
int num;
Scanner input = new Scanner(System.in);
System.out.println("请输入磁道数:");
num = input.nextInt();
int[] cidao=new int[num];
Random rand = new Random();
for(i = 0; i < num; i++) {
cidao[i] = rand.nextInt(200) + 1 ;
}
System.out.print("磁道序列为:");
for(i = 0; i < num; i++) {
System.out.print(cidao[i]+" ");
}
System.out.println();
Arrays.sort(cidao);
System.out.print("请输入当前的磁道号:");
Scanner w=new Scanner(System.in);
now=w.nextInt();
if(cidao[num-1]<=now) //若当前磁道号大于请求序列中最大者,则直接将移动臂移动到最小号磁道依次向外给予各请求服务
{
System.out.println("磁盘扫描序列为:");
for(i=0;i<num;i++)
System.out.print(cidao[i]+" ");
sum = now-2*cidao[0]+cidao[num-1];
}
if(cidao[0]>=now) //若当前磁道号小于请求序列中最小者,则直接由内向外依次给予各请求服务,此情况同最短寻道优先
{
System.out.println("磁盘扫描序列为:");
for(i=0;i<num;i++)
System.out.print(cidao[i]+" ");
sum=cidao[num-1]-now;
}
if(now>cidao[0]&&now<cidao[num-1]) //若当前磁道号大于请求序列中最小者且小于最大者
{
System.out.println("磁盘扫描序列为:");
while(cidao[k]<now) //单向反复地从内向外扫描
{
k++;
}
l=k-1;
r=k;
for(j=r;j<num;j++)
{
System.out.print(cidao[j]+" ");
}
for(j=0;j<r;j++) //当扫描完最大号磁道,磁头直接移动到最小号磁道,再向外扫描未扫描的磁道
{
System.out.print(cidao[j]+" ");
}
sum=2*cidao[num-1]+cidao[l]-now-2*cidao[0];
}
ave=(float)(sum)/(float)(num);
System.out.println();
System.out.println("平均寻道长度: "+ave);
}
}