磁盘调度算法的模拟与实现

1、实验目的

(1) 了解磁盘结构以及磁盘上数据的组织方式。
(2) 掌握磁盘访问时间的计算方式。
(3) 掌握常用磁盘调度算法及其相关特性。

2、实验基本知识及原理

(1)磁盘数据的组织
磁盘上每一条物理记录都有唯一的地址,该地址包括三个部分:磁头号(盘面号)、柱面号(磁
道号)和扇区号。给定这三个量就可以唯一地确定一个地址。
(2)磁盘访问时间的计算方式
磁盘在工作时以恒定的速率旋转。为保证读或写,磁头必须移动到所要求的磁道上,当所要求
的扇区的开始位置旋转到磁头下时,开始读或写数据。对磁盘的访问时间包括:寻道时间、旋转延
迟时间和传输时间。
(3)磁盘调度算法
磁盘调度的目的是要尽可能降低磁盘的寻道时间,以提高磁盘 I/O 系统的性能。
先进先出算法 FIFO:按访问请求到达的先后次序进行调度。
最短服务时间优先算法 SSTF:优先选择使磁头臂从当前位置开始移动最少的磁盘 I/O 请求进行调度。
SCAN(电梯算法):要求磁头臂先沿一个方向移动,并在途中满足所有未完成的请求,直到它到达这个方向上的最后一个磁道,或者在这个方向上没有别的请求为止,后一种改进有时候称作LOOK 策略。然后倒转服务方向,沿相反方向扫描,同样按顺序完成所有请求。
C-SCAN(循环扫描)算法:在磁盘调度时,把扫描限定在一个方向,当沿某个方向访问到最后一个磁道时,磁头臂返回到磁盘的另一端,并再次开始扫描。

3、实验内容

本实验通过编程模拟实现几种常见的磁盘调度算法。
(1)测试数据:参见教材 P305,测试结果参见表 11.2。
(2)使用 C 语言编程实现 FIFO、SSTF、SCAN、C-SCAN 算法。

4、 实验结果与分析

5、 实验总结

如果想了解一下磁盘调度算法,我推荐B站上一个up的视频,很简短,十分钟讲的很清楚,他的id为:楚丶雨轩
是这个视频:当然,听我讲也是可以的。在这里插入图片描述

----------------------相 关---------------------------

我是用Dec C++进行编写的,用的语言是C语言
代码不多讲,都是基础语句,部分代码也有详细注释

咳咳,开始正题。

----------------------主函数---------------------------

首先,我的主函数中主要是输入磁道数量以及磁道序列,然后是几种算法的选择,通过switch语句的输出来进行调度算法的选择。

首先是输入磁道数量以及序列

	printf("请先输入磁道数量: \n");
    scanf("%d",&b);
    printf("请先输入 %d 个磁道序列: \n",b);
    for(i=0; i<b; i++)
    {
        scanf("%d",&cidao[i]);
    }
    

在输出调度算法的选择操作

  		printf("\n 算法选择: \n");
        printf(" 1、先进先出算法( FIFO) \n");
        printf(" 2、最短服务时间优先算法( SSTF) \n");
        printf(" 3、扫描算法( SCAN) \n");
        printf(" 4、循环扫描算法( C-SCAN) \n");
        printf(" 5. 退出\n");
        printf("\n");
        printf("请选择: ");
        scanf("%d",&c);

然后使用switch语句进行输出:

	switch(c)//算法选择
	        {
		        case 1:
		            FIFO(cidao,count);//先进先出算法,自定义函数
		            printf("\n");
		            break;
		        case 2:
		            SSTF(cidao,count);//最短服务时间优先算法
		            printf("\n");
		            break;
		        case 3:
		            SCAN(cidao,count);//扫描算法
		            printf("\n");
		            break;
		        case 4:
		            CSCAN(cidao,count);//循环扫描算法
		            printf("\n");
		            break;
		        case 5:
		            exit(0);
	        }

总体的效果如下:
在这里插入图片描述

----------------------先进先出(FIFO)算法---------------------------

先进先出算法就是 按输入的顺序依次进行访问

就例如我刚刚输入的10,85,35,150,3,这个序列。它的访问顺序就是从10开始,然后85,35,150,最后是3。

磁道与磁道之间相隔距离就是两磁道序列之间差的绝对值。10和85之间的相隔距离就是(85-10)=75,这个75就是相隔距离。

一般用来比较各个算法之间的速度的量就是平均寻道长度,就是全部磁道相隔距离除以磁道数。如果我输入当前所在的磁道号为15,那么平均寻道长度就是 [(15-10)+75+(85-35)+(150-35)+(150-3)] / 5 =78.400002

    int sum=0,j,i,now;
    float avg;
    
    printf("\n 请输入当前所在的磁道号: ");
    scanf("%d",&now);
    printf("\n FIFO 调度结果: ");
    printf("%d ",now);
    for(i=0; i<m; i++) 
		printf("%d ",array[i]);
	
    sum=abs(now-array[0]);   //abs取绝对值
	printf("\n 磁道与磁道之间相隔距离: %d ",sum);
    for(j=1; j<m; j++) 
    {
    	int n=0;
    	n=abs(array[j]-array[j-1]);  //两个磁道间相差的距离 
    	sum+=n; //累计总的移动距离
    	printf("%d ",n);
	}	
    avg=(float)sum/m;//计算平均寻道长度
    printf("\n 平均寻道长度: %f \n",avg);

运行结果显示就是如图
在这里插入图片描述

----------------------最短服务时间优先(SSTF)算法---------------------------

最短服务时间优先就是先将输入的磁道从小到大进行排序,然后将当前的磁道号与比他大一个的数和比他小一个的数进行比较【计算磁道相隔距离(如有不知,请翻回先进先出算法处,由详细说明)】,选择磁道相隔距离小的进行访问。

就例如我输入磁道,首先进行排序,则是3,10,35,85,150。然后我输入当前的磁道号为17,它在磁道10和磁道35的中间。比它大一个的数是磁道35,比它小一个的数是磁道10,磁道17和磁道35之间的相隔距离为18,和磁道10的相隔距离为7。选择相隔距离小的进行访问,所以先访问磁道10。
然后当前磁道号就变成了10,比他大一个的数为磁道35,比他小一个的数为磁道3,相隔距离分别是25和7,所以访问磁道3。
当前磁道号为3,上下两个数为35和150,相隔距离分别是32和147,所以访问磁道35。
依次类推。。。。。。。。。。访问的顺序就是10,3,35,85,150.

可以把排序后的磁道看作是一个圈,就挺好理解的。图有点抽象,希望你们能看懂[哭泣脸]。
紫色的就是我说的圈,黑色的数字就是磁道号,红色那个是输入的当前磁道号。自行理解吧,我绘画水平仅限于此。
在这里插入图片描述

    int temp;
    int k=1;
    int now,l,r;
    int i,j,sum=0;
    float avg;
    
    for(i=0; i<m; i++)
    {
        for(j=i+1; j<m; j++) //对磁道号进行从小到大排列
        {
            if(array[i]>array[j])//两磁道号之间比较
            {
                temp=array[i];
                array[i]=array[j];
                array[j]=temp;
            }
        }
    }
    
     printf("磁道从小到大的排序: ");
    for( i=0; i<m; i++) //输出排序后的磁道号数组
        printf(" %d ",array[i]);
    
    printf("\n 请输入当前的磁道号: ");
    scanf("%d",&now);
    
    printf("\n SSTF 调度结果: ");
    
    if(array[m-1]<=now)//整个数组里的数都小于当前磁道号
    {
        for(i=m-1; i>=0; i--) //将数组磁道号从大到小输出
            printf("%d ",array[i]);
        sum=now-array[0];//移动距离 = 当前磁道号减去最小磁道号
    }
    else if(array[0]>=now)//整个数组里的数都大于当前磁道号
    {
        for(i=0; i<m; i++) //将磁道号从小到大输出
            printf("%d ",array[i]); 
        sum=array[m-1]-now;//移动距离 = 最大磁道号减去当前磁道号 
    }
    else   //当前磁道号在各个磁道号的中间 
    {
        while(array[k]<now)//逐一比较以确定 K 值,确定当前磁道号的位置 
        {
            k++;
        }
        l=k-1;
        r=k;
        
		//确定当前磁道在已排的序列中的位置
        while((l>=0)&&(r<m))
        {
            if((now-array[l])<=(array[r]-now))//当前磁道与前一个数据的距离小于和后一个数据距离
            {
				printf("%d ",array[l]);
                sum+=now-array[l];//计算移动距离
                now=array[l];  
                l=l-1; 
				//然后将数组向前移动,再次进行判断 
            }
            else //当前磁道与前一个数据的距离大于和后一个数据距离
            {
                printf("%d ",array[r]);
                sum+=array[r]-now;//计算移动距离
                now=array[r];
                r=r+1;
                //然后将数组向后移动,再次进行判断
            }
        }
        
        if(l=-1)
        {
            for(j=r; j<m; j++)
            {
                printf("%d ",array[j]);
            }
            sum+=array[m-1]-array[0];//计算移动距离
        }
        else
        {
            for(j=l; j>=0; j--)
            {
                printf("%d ",array[j]);
            }
            sum+=array[m-1]-array[0];//计算移动距离
        }
    }
    
    avg=(float)sum/m;
    printf("\n 平均寻道长度: %f \n",avg);

运行结果:
在这里插入图片描述

----------------------扫描(SCAN)算法---------------------------

扫描算法,还是先将磁道号进行由小到大的排序,然后从当前磁道数开始,依次访问比他大的数,最后在访问比它小的,又称电梯算法,就像坐电梯,先上升后下降

例如我输入磁道,首先进行排序,则是3,10,35,85,150。然后我输入当前的磁道号为20,然后它先访问比他大的数,依次是35,85,150。然后访问比它小的10,最后是3。就像是坐电梯从20楼先上升,先到35楼,然后到85楼,然后到150楼最高层开始下降,下降过程,先到10楼,再到3楼。所以访问的顺序就是35,85,150,10,3.

也可以看成一个圈(继续感受我画图的水平趴),红色的是输入的当前磁道号,绿色的是先访问路径,橙色的是后访问路径。
在这里插入图片描述
对于我来说,还是电梯好理解一些。
在这里插入图片描述

 	int sum=0;
    for(int i=0; i<m; i++)
    {
        for(int j=i+1; j<m; j++) //对磁道号进行从小到大排列
        {
            if(array[i]>array[j])//两磁道号之间比较
            {
                int temp=array[i];
                array[i]=array[j];
                array[j]=temp;
            }
        }
    }
    
    printf("磁道从小到大的排序: ");
    for(int i=0; i<m; i++)
    {
        printf("%d ",array[i]);
    }
    
    printf("\n 请输入当前的磁道号: ");
    int now;
    scanf("%d",&now);
    printf("\n SCAN 调度结果:");
    int pos;
    for(int i=0; i<m; i++)
    {
        if(array[i]>=now)  //判断当前磁道号的位置 
        {
            pos=i;
            sum+=abs(array[i]-now);   
            break;
        }
    }
    
    for(int i=pos; i<m; i++)  //先输出比当前磁道大的磁道 
    {
        if(i!=pos)
            sum+=abs(array[i]-array[i-1]);
        printf("%d ",array[i]);
    }
    
    if(pos>=1)
        sum+=abs(array[m-1]-array[pos-1]);
        
    for(int i=pos-1; i>=0; i--)  //输出比当前磁道小的磁道 
    {
        if(i)
            sum+=abs(array[i]-array[i-1]);
        printf("%d ",array[i]);
    }
    printf("\n 平均寻道长度:%f\n",1.0*sum/m);

运行结果:
在这里插入图片描述

----------------------循环扫描(CSCAN)算法---------------------------

循环扫描算法和扫描算法很相似,但循环算法不同的一点在于它访问到最大磁道后就从最小磁道开始访问。

例如我输入磁道,首先进行排序,则是3,10,35,85,150。然后我输入当前的磁道号为25,然后它先访问比他大的数,依次是35,85,150。然后访问3,最后是10(扫描算法是先访问10,最后是3),这也是被称作循环算法的原因。

用一张图就很好理解。
在这里插入图片描述

 int sum=0;
    for(int i=0; i<m; i++)
    {
        for(int j=i+1; j<m; j++) //对磁道号进行从小到大排列
        {
            if(array[i]>array[j])//两磁道号之间比较
            {
                int temp=array[i];
                array[i]=array[j];
                array[j]=temp;
            }
        }
    }
    for(int i=0; i<m; i++)
    {
        printf("%d ",array[i]);
    }
    printf("\n 请输入当前的磁道号: ");
    int now;
    scanf("%d",&now);
    printf("\n C-SCAN 调度结果:");
    int pos;
    
    for(int i=0; i<m; i++)  //判断当前磁道号的位置 
    {
        if(array[i]>=now)
        {
            pos=i;
            sum+=abs(array[i]-now);
            break;
        }
    }
    
    for(int i=pos; i<m; i++)
    {
        if(i!=pos)
            sum+=abs(array[i]-array[i-1]);
        printf("%d ",array[i]);
    }
    
    if(pos>=1)
        sum+=abs(array[m-1]-array[0]);
    for(int i=0; i<pos; i++)
    {
        if(i)
            sum+=abs(array[i]-array[i-1]);
        printf("%d ",array[i]);
    }
    printf("\n 平均寻道长度:%f\n",1.0*sum/m);

运行结果:
在这里插入图片描述

----------------------源代码---------------------------

#include <iostream>
#include<stdio.h>
#include <stdlib.h>
using namespace std; 

#define maxsize 1000 //定义最大数组域

//------------先进先出(FIFO)调度算法-----------------
void FIFO(int array[],int m)
{
    int sum=0,j,i,now;
    float avg;
    
    printf("\n 请输入当前所在的磁道号: ");
    scanf("%d",&now);
    printf("\n FIFO 调度结果: ");
    printf("%d ",now);
    for(i=0; i<m; i++) 
		printf("%d ",array[i]);
	
    sum=abs(now-array[0]);   //abs取绝对值
	printf("\n 磁道与磁道之间相隔距离: %d ",sum);
    for(j=1; j<m; j++) 
    {
    	int n=0;
    	n=abs(array[j]-array[j-1]);  //两个磁道间相差的距离 
    	sum+=n; //累计总的移动距离
    	printf("%d ",n);
	}	
    avg=(float)sum/m;//计算平均寻道长度
    printf("\n 平均寻道长度: %f \n",avg);
}


//------------最短服务时间优先(SSTF)调度算法-----------
void SSTF(int array[],int m)
{
    int temp;
    int k=1;
    int now,l,r;
    int i,j,sum=0;
    float avg;
    
    for(i=0; i<m; i++)
    {
        for(j=i+1; j<m; j++) //对磁道号进行从小到大排列
        {
            if(array[i]>array[j])//两磁道号之间比较
            {
                temp=array[i];
                array[i]=array[j];
                array[j]=temp;
            }
        }
    }
    
     printf("磁道从小到大的排序: ");
    for( i=0; i<m; i++) //输出排序后的磁道号数组
        printf(" %d ",array[i]);
    
    printf("\n 请输入当前的磁道号: ");
    scanf("%d",&now);
    
    printf("\n SSTF 调度结果: ");
    
    if(array[m-1]<=now)//整个数组里的数都小于当前磁道号
    {
        for(i=m-1; i>=0; i--) //将数组磁道号从大到小输出
            printf("%d ",array[i]);
        sum=now-array[0];//移动距离 = 当前磁道号减去最小磁道号
    }
    else if(array[0]>=now)//整个数组里的数都大于当前磁道号
    {
        for(i=0; i<m; i++) //将磁道号从小到大输出
            printf("%d ",array[i]); 
        sum=array[m-1]-now;//移动距离 = 最大磁道号减去当前磁道号 
    }
    else   //当前磁道号在各个磁道号的中间 
    {
        while(array[k]<now)//逐一比较以确定 K 值,确定当前磁道号的位置 
        {
            k++;
        }
        l=k-1;
        r=k;
        
		//确定当前磁道在已排的序列中的位置
        while((l>=0)&&(r<m))
        {
            if((now-array[l])<=(array[r]-now))//当前磁道与前一个数据的距离小于和后一个数据距离
            {
				printf("%d ",array[l]);
                sum+=now-array[l];//计算移动距离
                now=array[l];  
                l=l-1; 
				//然后将数组向前移动,再次进行判断 
            }
            else //当前磁道与前一个数据的距离大于和后一个数据距离
            {
                printf("%d ",array[r]);
                sum+=array[r]-now;//计算移动距离
                now=array[r];
                r=r+1;
                //然后将数组向后移动,再次进行判断
            }
        }
        
        if(l=-1)
        {
            for(j=r; j<m; j++)
            {
                printf("%d ",array[j]);
            }
            sum+=array[m-1]-array[0];//计算移动距离
        }
        else
        {
            for(j=l; j>=0; j--)
            {
                printf("%d ",array[j]);
            }
            sum+=array[m-1]-array[0];//计算移动距离
        }
    }
    
    avg=(float)sum/m;
    printf("\n 平均寻道长度: %f \n",avg);
}

//------------------------扫描算法---------------------
void SCAN(int array[],int m)
{
    int sum=0;
    for(int i=0; i<m; i++)
    {
        for(int j=i+1; j<m; j++) //对磁道号进行从小到大排列
        {
            if(array[i]>array[j])//两磁道号之间比较
            {
                int temp=array[i];
                array[i]=array[j];
                array[j]=temp;
            }
        }
    }
    
    printf("磁道从小到大的排序: ");
    for(int i=0; i<m; i++)
    {
        printf("%d ",array[i]);
    }
    
    printf("\n 请输入当前的磁道号: ");
    int now;
    scanf("%d",&now);
    printf("\n SCAN 调度结果:");
    int pos;
    for(int i=0; i<m; i++)
    {
        if(array[i]>=now)  //判断当前磁道号的位置 
        {
            pos=i;
            sum+=abs(array[i]-now);   
            break;
        }
    }
    
    for(int i=pos; i<m; i++)  //先输出比当前磁道大的磁道 
    {
        if(i!=pos)
            sum+=abs(array[i]-array[i-1]);
        printf("%d ",array[i]);
    }
    
    if(pos>=1)
        sum+=abs(array[m-1]-array[pos-1]);
        
    for(int i=pos-1; i>=0; i--)  //输出比当前磁道小的磁道 
    {
        if(i)
            sum+=abs(array[i]-array[i-1]);
        printf("%d ",array[i]);
    }
    printf("\n 平均寻道长度:%f\n",1.0*sum/m);
}

//------------------循环扫描算法---------------------
void CSCAN(int array[],int m)
{
    int sum=0;
    for(int i=0; i<m; i++)
    {
        for(int j=i+1; j<m; j++) //对磁道号进行从小到大排列
        {
            if(array[i]>array[j])//两磁道号之间比较
            {
                int temp=array[i];
                array[i]=array[j];
                array[j]=temp;
            }
        }
    }
    for(int i=0; i<m; i++)
    {
        printf("%d ",array[i]);
    }
    printf("\n 请输入当前的磁道号: ");
    int now;
    scanf("%d",&now);
    printf("\n C-SCAN 调度结果:");
    int pos;
    
    for(int i=0; i<m; i++)  //判断当前磁道号的位置 
    {
        if(array[i]>=now)
        {
            pos=i;
            sum+=abs(array[i]-now);
            break;
        }
    }
    
    for(int i=pos; i<m; i++)
    {
        if(i!=pos)
            sum+=abs(array[i]-array[i-1]);
        printf("%d ",array[i]);
    }
    
    if(pos>=1)
        sum+=abs(array[m-1]-array[0]);
    for(int i=0; i<pos; i++)
    {
        if(i)
            sum+=abs(array[i]-array[i-1]);
        printf("%d ",array[i]);
    }
    printf("\n 平均寻道长度:%f\n",1.0*sum/m);
}
// 操作界面
int main()
{
    int c;
    int count;
//int m=0;
    int cidao[maxsize];//定义磁道号数组
    int i=0;
    int b;
    printf("请先输入磁道数量: \n");
    scanf("%d",&b);
    printf("请先输入 %d 个磁道序列: \n",b);
    for(i=0; i<b; i++)
    {
        scanf("%d",&cidao[i]);
    }
    
    printf("\n 磁道读取结果: \n");
    for(i=0; i<b; i++)
    {
        printf("%d ",cidao[i]);//输出读取的磁道的磁道号
    }
    count=b;
    printf("\n ");
    
    while(1)
    {
        printf("\n 算法选择: \n");
        printf(" 1、先进先出算法( FIFO) \n");
        printf(" 2、最短服务时间优先算法( SSTF) \n");
        printf(" 3、扫描算法( SCAN) \n");
        printf(" 4、循环扫描算法( C-SCAN) \n");
        printf(" 5. 退出\n");
        printf("\n");
        printf("请选择: ");
        scanf("%d",&c);
        if(c>5)
			printf("输入的选择错误,请从重新选择!");
		else{
			switch(c)//算法选择
	        {
		        case 1:
		            FIFO(cidao,count);//先进先出算法
		            printf("\n");
		            break;
		        case 2:
		            SSTF(cidao,count);//最短服务时间优先算法
		            printf("\n");
		            break;
		        case 3:
		            SCAN(cidao,count);//扫描算法
		            printf("\n");
		            break;
		        case 4:
		            CSCAN(cidao,count);//循环扫描算法
		            printf("\n");
		            break;
		        case 5:
		            exit(0);
	        }
		} 
        
    }
    return 0;
}

运行结果:
在这里插入图片描述

  • 7
    点赞
  • 59
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值