磁盘调度算法实现
在计算机操作系统中,磁盘调度的算法通常有以下几种:
一、先到先服务算法FCFS( First Come First Serve)
顾名思意,FCFS算法是按照输入/输出的先后次序为各个进程服务,即依请求次序访问磁道。
请求次序:1 2 3 4 5 6
访问磁道:34 33 98 76 2 88
如上所示,FCFS依次访问磁道34,33,98,76,2,88,总移动磁道数为:1+65+22+74+86=248.
此算法易于实现,但效率低下,适合于负载很轻的系统。
FCFS代码实现如下:
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#include<math.h>
#define DISKMAX 1000
#define DISKTOTAL 1000
#define OK 1
#define ERROR -1
/*先到先服务磁盘调度*/
void FCFS(int *R,int present_disk,int request_num){
int i;
int count=0; //磁头移动总次数
int step; //访问下一个磁道磁头移动次数
printf("\nMoving Order Moving Path Moving Steps");
step=abs(present_disk-R[0]); /*绝对值*/
count+=step;
printf("\n 1 %d---->%d %d",present_disk,R[0], step);/*输出访问轨迹*/
for(i=0;i<request_num-1;i++){ /*遍历数组*/
step=abs(R[i]-R[i+1]);
count+=step;
printf("\n %d %d---->%d %d",i+2,R[i],R[i+1], step);
}
printf("\nTotal moving steps:%d",count); /*输出磁头总移动次数*/
printf("\nAverage moving steps:%d",count/request_num); /*平均移动次数*/
}
运行结果如下:
input number of base disk(1~1000):100 (模拟产生多少个磁道)
The base disk is:
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53
54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78
79 80 81 8283 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99
input number of request disk(1~1000):(模拟产生多少个请求)
6
System creates stochastic numbers for request disk :
22 17 27 9 8 78
input present disk number(0~99):2 (当前磁头在哪个磁道)
(输出结果)
Moving Order Moving Path Moving Steps
1 2---->22 20
2 22---->17 5
3 17---->27 10
4 27---->9 18
5 9---->8 1
6 8---->78 70
Total moving steps:124
Average moving steps:20
二、最短寻道时间优先算法SSTE(Shortest Seek Time First)
SSTE基于这样的思想:磁头总是访问距离当前磁道最近的磁道。
请求次序:1 2 3 4 5 6
访问磁道:34 33 98 76 2 88
如上所示,SSTE依次访问磁道34,33,2,76,88,98,总移动磁道数为:1+31+74+12+10=128,比FCFS的248道访问总数少了很多。
SSTE的实现代码如下:
/*最短寻道时间优先算法*/
void SSTF(int *R,int present_disk,int request_num){
int i=0;
int temp,key;
int count=0,step=0;
int up=0,down=0;
int up_step=0,down_step=0;
key=SearchPresent(R,request_num , present_disk); /*查找当前磁道*/
printf("\nMoving Order Moving Path Moving Steps");
while(key!=0&&key!=request_num){ /*磁道未到头或尾*/
i++;
if((R[key]-R[key-1-down])<(R[key+1+up]-R[key])){ /*左边的磁道比右边的磁道近*/
temp=key-1-down; /*记录下一个磁道*/
down_step++;
down=0;
up=down_step+up_step;
}
else { /*右边的磁道比左边的磁道近*/
temp=key+1+up; /*记录下一个磁道*/
up_step++;
up=0;
down=up_step+down_step;
}
step=abs(R[key]-R[temp]);
count+=step;
printf("\n %d %d---->%d %d",i,R[key],R[temp], step);
key=temp;
}
if(key==0){ /*当前磁头在头*/
i++;
temp=key+1+up; /*记录下一个将要访问的磁道*/
step=abs(R[key]-R[temp]);
count+=step;
printf("\n %d %d---->%d %d",i,R[key],R[temp], step);
key=temp;
while(key!=request_num){
i++;
step=R[key+1]-R[key];
count+=step;
printf("\n %d %d---->%d %d",i,R[key],R[key+1], step);
key++;
}
}
else{ /*当前磁头在尾*/
i++;
temp=key-1-down; /*记录下一个将要访问的磁道*/
step=abs(R[key]-R[temp]);
count+=step;
printf("\n %d %d---->%d %d",i,R[key],R[temp], step);
key=temp;
while(key!=0){
i++;
step=R[key]-R[key-1];
count+=step;
printf("\n %d %d---->%d %d",i,R[key],R[key-1], step);
key--;
}
}
printf("\nTotal moving steps:%d",count);
printf("\nAverage moving steps:%d",count/request_num);
}
运行结果如下:
Moving Order Moving Path Moving Steps
1 2---->8 6
2 8---->9 1
3 9---->17 8
4 17---->22 5
5 22---->27 5
6 27---->78 51
Total moving steps:76
Average moving steps:12
三、电梯算法(扫描算法)Scan
电梯算法其基本思想与电梯工作原理类似:最开始的时候,磁头向访问请求的方向A扫描,在磁头移动过程中,如果经过的磁道有访问请求,则为其服务。接着判断A方向是否仍有请求,有则向A移动处理,否则调转方向向B移动:
其代码实现如下:
/*电梯扫描算法*/
void SCAN(int *R,int present_disk,int request_num){
int i=0;
int temp,key;
int count=0,step=0;
key=SearchPresent(R,request_num , present_disk); /*查找当前磁道*/
temp=key;
if(key==request_num){ /*当前磁头在磁道头*/
while(key!=0){ /*向内移动*/
step=R[key]-R[key-1];
count+=step;
printf("\n %d %d---->%d %d",i+1,R[key],R[key-1], step);
key--;
i++;
}
}
else if(key==0){ /*当前磁头在磁道尾*/
while(key!=request_num){
step=R[key+1]-R[key];
count+=step;
printf("\n %d %d---->%d %d",i+1,R[key],R[key+1], step);
key++;
i++;
}
}
else{ /*当前磁头不在头或尾*/
while(key!=0){ /*向内移动*/
step=R[key]-R[key-1];
count+=step;
printf("\n %d %d---->%d %d",i+1,R[key],R[key-1], step);
key--;
i++;
}
/*向外移动*/
i++;
step=R[temp+1]-R[key];
count+=step;
printf("\n %d %d---->%d %d",i,R[key],R[temp+1], step);
key=temp+1;
while(key!=request_num){
step=R[key+1]-R[key];
count+=step;
printf("\n %d %d---->%d %d",i+1,R[key],R[key+1], step);
key++;
i++;
}
}
printf("\nTotal moving steps:%d",count);
printf("\nAverage moving steps:%d",count/request_num);
}
运行结果如下:
Moving Order Moving Path Moving Steps
1 2---->8 6
2 8---->9 1
3 9---->17 8
4 17---->22 5
5 22---->27 5
6 27---->78 51
Total moving steps:76
Average moving steps:12
四、总结
以上用代码实现了磁盘调度的一些算法,并简单地分析了算法的基本思想。
完整代码如下:
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#include<math.h>
#define DISKMAX 1000
#define DISKTOTAL 1000
#define OK 1
#define ERROR -1
int cmp ( const void *a , const void *b ) /**/
{
return *(int *)a - *(int *)b;
}
void SetBaseDisk(int *base_num){/*设置磁盘磁道数*/
int i;
printf("\ninput number of base disk(1~%d):",DISKMAX);
scanf("%d",base_num);
if(*base_num<=0||*base_num>DISKMAX){printf("ERROR!");exit(0);}
printf("\nThe base disk is:\n");
for(i=0;i<*base_num;i++){
printf(" %d",i);
}
}
void SetRequestDisk(int *R,int *request_num,int base_num){/*设置请求访问磁道数*/
int i;
srand(time(NULL));
printf("\ninput number of request disk(1~%d)",DISKTOTAL);
scanf("%d",request_num);
if(*request_num<=0||*request_num>DISKTOTAL){printf("ERROR!");exit(0);}
printf("\nSystem creates stochastic numbers for request disk :\n");
for(i=0;i<*request_num;i++){
R[i]=rand()%(base_num-1);//生成随机数
printf(" %d",R[i]);
}
}
void SetPresentDisk(int *present_disk,int *base_num){/*设置当前磁道*/
printf("\ninput present disk number(0~%d):",*base_num-1);
scanf("%d",present_disk);
if(*present_disk<0||*present_disk>=*base_num){printf("ERROR!");exit(0);}
}
/*先到先服务磁盘调度*/
void FCFS(int *R,int present_disk,int request_num){
int i;
int count=0; //磁头移动总次数
int step; //访问下一个磁道磁头移动次数
printf("\nMoving Order Moving Path Moving Steps");
step=abs(present_disk-R[0]); /*绝对值*/
count+=step;
printf("\n 1 %d---->%d %d",present_disk,R[0], step);/*输出访问轨迹*/
for(i=0;i<request_num-1;i++){ /*遍历数组*/
step=abs(R[i]-R[i+1]);
count+=step;
printf("\n %d %d---->%d %d",i+2,R[i],R[i+1], step);
}
printf("\nTotal moving steps:%d",count); /*输出磁头总移动次数*/
printf("\nAverage moving steps:%d",count/request_num); /*平均移动次数*/
}
int Sort(int *R,int request_num,int present_disk){/*调用库函数的快速排序函数*/
R[request_num]=present_disk;//加入当前磁道
qsort(R,request_num+1,sizeof(R[0]),cmp);
return 1;
}
int SearchPresent(int *R,int request_num ,int present_disk){/*二分查找法,寻找当前磁道*/
int left,right,middle;
left=0;
right=request_num;
while(left<=right){
middle=(left+right)/2;
if(present_disk==R[middle])return middle;
if(present_disk>R[middle])left=middle+1;
else right=middle-1;
}
return -1;
}
/*最短寻道时间优先算法*/
void SSTF(int *R,int present_disk,int request_num){
int i=0;
int temp,key;
int count=0,step=0;
int up=0,down=0;
int up_step=0,down_step=0;
key=SearchPresent(R,request_num , present_disk); /*查找当前磁道*/
printf("\nMoving Order Moving Path Moving Steps");
while(key!=0&&key!=request_num){ /*磁道未到头或尾*/
i++;
if((R[key]-R[key-1-down])<(R[key+1+up]-R[key])){ /*左边的磁道比右边的磁道近*/
temp=key-1-down; /*记录下一个磁道*/
down_step++;
down=0;
up=down_step+up_step;
}
else { /*右边的磁道比左边的磁道近*/
temp=key+1+up; /*记录下一个磁道*/
up_step++;
up=0;
down=up_step+down_step;
}
step=abs(R[key]-R[temp]);
count+=step;
printf("\n %d %d---->%d %d",i,R[key],R[temp], step);
key=temp;
}
if(key==0){ /*当前磁头在头*/
i++;
temp=key+1+up; /*记录下一个将要访问的磁道*/
step=abs(R[key]-R[temp]);
count+=step;
printf("\n %d %d---->%d %d",i,R[key],R[temp], step);
key=temp;
while(key!=request_num){
i++;
step=R[key+1]-R[key];
count+=step;
printf("\n %d %d---->%d %d",i,R[key],R[key+1], step);
key++;
}
}
else{ /*当前磁头在尾*/
i++;
temp=key-1-down; /*记录下一个将要访问的磁道*/
step=abs(R[key]-R[temp]);
count+=step;
printf("\n %d %d---->%d %d",i,R[key],R[temp], step);
key=temp;
while(key!=0){
i++;
step=R[key]-R[key-1];
count+=step;
printf("\n %d %d---->%d %d",i,R[key],R[key-1], step);
key--;
}
}
printf("\nTotal moving steps:%d",count);
printf("\nAverage moving steps:%d",count/request_num);
}
/*电梯扫描算法*/
void SCAN(int *R,int present_disk,int request_num){
int i=0;
int temp,key;
int count=0,step=0;
key=SearchPresent(R,request_num , present_disk); /*查找当前磁道*/
temp=key;
if(key==request_num){ /*当前磁头在磁道头*/
while(key!=0){ /*向内移动*/
step=R[key]-R[key-1];
count+=step;
printf("\n %d %d---->%d %d",i+1,R[key],R[key-1], step);
key--;
i++;
}
}
else if(key==0){ /*当前磁头在磁道尾*/
while(key!=request_num){
step=R[key+1]-R[key];
count+=step;
printf("\n %d %d---->%d %d",i+1,R[key],R[key+1], step);
key++;
i++;
}
}
else{ /*当前磁头不在头或尾*/
while(key!=0){ /*向内移动*/
step=R[key]-R[key-1];
count+=step;
printf("\n %d %d---->%d %d",i+1,R[key],R[key-1], step);
key--;
i++;
}
/*向外移动*/
i++;
step=R[temp+1]-R[key];
count+=step;
printf("\n %d %d---->%d %d",i,R[key],R[temp+1], step);
key=temp+1;
while(key!=request_num){
step=R[key+1]-R[key];
count+=step;
printf("\n %d %d---->%d %d",i+1,R[key],R[key+1], step);
key++;
i++;
}
}
printf("\nTotal moving steps:%d",count);
printf("\nAverage moving steps:%d",count/request_num);
}
int main(){
int R[DISKTOTAL];
int base_num,request_num,present_disk;
int choose;
int flag=0;
SetBaseDisk( &base_num);
SetRequestDisk(R,&request_num,base_num);
SetPresentDisk(&present_disk,&base_num);
do{
printf("\n/*********************************/");
printf("\n\n1.先到先服务FCFS磁盘调度算法");
printf("\n\n2.最短寻道时间优先SSTF磁盘调度算法");
printf("\n\n3.电梯扫描算法SCAN磁盘调度算法");
printf("\n\n4.退出.");
printf("\n\n/*******************************/");
printf("\n\n请输入您的选择:(1 , 2 , 3 ,4 )");
scanf("%d",&choose);//输入选择
switch(choose){
case 1:{
FCFS(R,present_disk,request_num);
}break;
case 2:{
if(flag==0)flag=Sort(R,request_num,present_disk); //排序
SSTF(R,present_disk,request_num);
}break;
case 3:{
if(flag==0)flag=Sort(R,request_num,present_disk); //排序
SCAN(R,present_disk,request_num);
}break;
}/*switch*/
}
while(choose>=1&&choose<4);
printf("\n再见!");
return 0;
}