在计算机操作系统中,磁盘调度的算法通常有以下几种:
一、先到先服务算法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 < 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 ;
}