操作系统 磁盘调度算法

以下两种算法的代码均是在c++环境下编译进行

SSTF调度

初版:

#include <bits/stdc++.h>
#define inf 0x3f3f3f3f
using namespace std;

int a[1010],n;
bool book[1010];

void change(int u)
{
    int i,num=inf,minn=inf,flag;
    for(i=0; i<n; i++)
        if(abs(a[i]-u)<minn&&book[i]==0)
        {
            minn=abs(a[i]-u);
            flag=a[i];
            num=i;
        }
    if(num==inf)
        return;
    book[num]=1;
    printf("%d\t\t\t%d\n",flag,minn);
    change(flag);
    return;
}

int main()
{
    int i,m;
    memset(book,0,sizeof(book));
    printf("请输入访盘个数:");
    scanf("%d",&n);
    printf("\n");
    printf("请输入访盘序列:");
    for(i=0; i<n; i++)
        scanf("%d",&a[i]);
    printf("\n");
    printf("请输入当前磁道号:");
    scanf("%d",&m);
    printf("\n");
    printf("被访问的下一个磁道号\t移动距离(磁道数)\n");
    change(m);
    return 0;
}

最终版:

//SSTF调度

#include <bits/stdc++.h>//c++万能头文件

#define Coding author 孙黎明 19110543033

#define inf 0x3f3f3f3f//定义inf为无穷大
using namespace std;
//下面变量开全局,可以在main函数和自定义函数中同时使用,避免了传参数这一步骤
int a[1010];//定义数组a,用来保存访盘序列
int n;//n代表访盘个数
bool book[1010];//book[a]=1表示标号为a的访盘已经访问过,book[a]=0表示标号为a的访盘没有访问过。用来记录是否访问过,防止重复访问


void change(int u)//处理函数,用来处理访盘序列,同时给出被访问的下一个磁道号以及移动距离,u代表当前磁道号
{
    int i;
    int num=inf;//用来记录被访问的下一个磁道号的编号,后续将其标记,初始赋值为inf,可以根据后续num的值来判断递归是否结束
    int minn=inf;//保存最少的移动距离,初始值赋值为无穷大
    int flag;//记录被访问的下一个磁道号
    for(i=0; i<n; i++)//遍历整个访盘序列
        if(abs(a[i]-u)<minn&&book[i]==0)//如果一个磁道号与当前磁道号的差比最小值还要小,同时这个磁道号没有访问过(abs:绝对值函数)
        {
            minn=abs(a[i]-u);//更新最小值
            flag=a[i];//记录被访问的下一个磁道号
            num=i;//记录被访问的下一个磁道号的编号
        }
    if(num==inf)//如果num=inf的话,就说明所有磁盘都访问过了,代表该递归结束
        return;//return出去
    book[num]=1;//循环完成后,把最终确定的被访问的下一个磁道号的编号标记,代表这个编号的磁道号已经访问过了,后续不会再访问
    printf("%d\t\t\t%d\n",flag,minn);//输出被访问的下一个磁道号以及移动距离,\t用来规范格式
    change(flag);//递归思想,继续递归处理下一个磁道
    return;
}

int main()
{
    int i,m;
    memset(book,0,sizeof(book));//初始化book数组全为0,代表所有磁道都没访问过
    printf("请输入访盘个数:");
    scanf("%d",&n);//读入访盘个数
    printf("\n");
    printf("请输入访盘序列:");
    for(i=0; i<n; i++)//读入访盘序列
        scanf("%d",&a[i]);
    printf("\n");
    printf("请输入当前磁道号:");
    scanf("%d",&m);//读入当前磁道号
    printf("\n");
    printf("被访问的下一个磁道号\t移动距离(磁道数)\n");
    change(m);//开始第一次调用处理函数处理数据
    return 0;
}

输入样例1:

7
55 58 39 18 90 160 150
100

输出样例1:

被访问的下一个磁道号	移动距离(磁道数)
90			10
58			32
55			3
39			16
18			21
150			132
160			10

输入样例2:

8
1 3 5 50 49 55 100 9
3

输出样例2:

被访问的下一个磁道号	移动距离(磁道数)
3			0
1			2
5			4
9			4
49			40
50			1
55			5
100			45

CSCAN调度

初版:

#include <bits/stdc++.h>

using namespace std;

int main()
{
    int i,ans,n,m,a[1010],num,flag;
    printf("请输入访盘个数:");
    scanf("%d",&n);
    printf("\n");
    printf("请输入访盘序列:");
    for(i=0; i<n; i++)
        scanf("%d",&a[i]);
    sort(a,a+n);
    printf("\n");
    printf("请输入当前磁道号:");
    scanf("%d",&m);
    ans=m;
    printf("\n");
    for(i=0; i<n; i++)
        if(a[i]>=m)
        {
            flag=i;
            break;
        }
    printf("请输入磁头移动方向(向磁道号增加的方向请输入1,向磁道号减少的方向请输入0):");
    scanf("%d",&num);
    printf("被访问的下一个磁道号\t移动距离(磁道数)\n");
    if(num==1)
    {
        for(i=flag; i<n; i++)
        {
            printf("%d\t\t\t%d\n",a[i],abs(a[i]-m));
            m=a[i];
        }
        for(i=0; i<flag; i++)
        {
            printf("%d\t\t\t%d\n",a[i],abs(a[i]-m));
            m=a[i];
        }
    }
    else
    {
        for(i=flag-1; i>=0; i--)
        {
            printf("%d\t\t\t%d\n",a[i],abs(a[i]-m));
            m=a[i];
        }
        for(i=n-1; i>=flag; i--)
        {
            printf("%d\t\t\t%d\n",a[i],abs(a[i]-m));
            m=a[i];
        }
    }
    return 0;
}

最终版:

//CSCAN调度

#include <bits/stdc++.h>//c++万能头文件

#define Coding author 孙黎明 19110543033

using namespace std;

int main()
{
    int i;
    int ans;//用来保存最开始的那个磁道号
    int m;//当前磁道号
    int n;//访盘个数
    int a[1010];//用来保存访盘序列
    int num;//记录磁头移动方向,0代表向磁道号减少的方向移动,1代表向磁道号增加的方向移动
    int flag;//记录第一个大于等于当前磁道号的磁道的编号
    printf("请输入访盘个数:");
    scanf("%d",&n);//读入访盘个数
    printf("\n");
    printf("请输入访盘序列:");
    for(i=0; i<n; i++)//读入访盘序列
        scanf("%d",&a[i]);
    sort(a,a+n);//利用c++ STL中自带的排序函数排序(默认从小到大排)
    printf("\n");
    printf("请输入当前磁道号:");
    scanf("%d",&m);//读入当前磁道号
    ans=m;//把最开始的磁道号赋值给ans保存
    printf("\n");
    for(i=0; i<n; i++)//遍历整个访盘序列找出第一个大于等于当前磁道号的磁道
        if(a[i]>=m)
        {
            flag=i;//标记第一个大于等于当前磁道号的磁道的编号
            break;//因为只需要找第一个,所以找到后就break出去
        }
    printf("请输入磁头移动方向(向磁道号增加的方向请输入1,向磁道号减少的方向请输入0):");
    scanf("%d",&num);//读入磁头移动方向
    printf("被访问的下一个磁道号\t移动距离(磁道数)\n");
    if(num==1)//如果磁头是向磁道号增加的方向移动
    {
        for(i=flag; i<n; i++)//从第一个大于等于当前磁道号的磁道编号开始,从小到大,遍历整个访盘序列
        {
            printf("%d\t\t\t%d\n",a[i],abs(a[i]-m));//输出被访问的下一个磁道号和移动距离(abs绝对值函数,可以直接给出距离)
            m=a[i];//更新当前磁道号,更新为刚才被访问的那个磁道
        }
        for(i=0; i<flag; i++)//如果磁头到达最大处,就再从头开始到flag,遍历访盘序列,寻找被访问的下一个磁道号
        {
            printf("%d\t\t\t%d\n",a[i],abs(a[i]-m));//输出被访问的下一个磁道号和移动距离(abs绝对值函数,可以直接给出距离)
            m=a[i];//更新当前磁道号,更新为刚才被访问的那个磁道
        }
    }
    else//如果磁头是向磁道号减少的方向移动
    {
        a[flag]==ans ? i=flag : i=flag-1;//判断a[flag]是否等于ans,如果等于i就等于flag,否则i=flag-1。该步判断的意义在于如果a[flag]刚好等于ans的话就从a[flag]开始遍历,否则就代表a[flag-1]是第一个比ans小的磁道,那么就从a[flag-1]开始遍历
        for(; i>=0; i--)//道理和上一个差不多
        {
            printf("%d\t\t\t%d\n",a[i],abs(a[i]-m));//输出被访问的下一个磁道号和移动距离(abs绝对值函数,可以直接给出距离)
            m=a[i];//更新当前磁道号,更新为刚才被访问的那个磁道
        }
        for(i=n-1; a[flag]==ans ? i>flag : i>=flag; i--) //从最大的磁道开始遍历
        {
            printf("%d\t\t\t%d\n",a[i],abs(a[i]-m));//输出被访问的下一个磁道号和移动距离(abs绝对值函数,可以直接给出距离)
            m=a[i];//更新当前磁道号,更新为刚才被访问的那个磁道
        }
    }
    return 0;
}

输入样例1:

7
55 58 39 18 90 160 150
100
1

输出样例1:

被访问的下一个磁道号	移动距离(磁道数)
150			50
160			10
18			142
39			21
55			16
58			3
90			32

输入样例2:

7
55 58 39 18 90 160 150
90
0

输出样例2:

被访问的下一个磁道号	移动距离(磁道数)
90			0
58			32
55			3
39			16
18			21
160			142
150			10

算法或原理的实现思想:

算法:
算法就是磁盘调度算法,我选择的是SSTF调度算法和CSCAN调度算法。
SSTF算法(最短寻道时间优先):就是先选择一个离当前磁道最近的磁道访问,然后以此类推,我感觉就是递归思想,写一个函数,然后所有过程都是一样的,即上一个磁道和下一个磁道的关系,然后一直递归。
CSCAN算法(循环扫描):就是从当前磁道开始,有两种选择,1.磁头向磁道号增加的方向移动 2.磁头向磁道号减少的方向移动,具体过程就是模拟,但是其中我发现一个坑,这个后面在后面遇到的问题里再说。

遇到的问题:
SSTF算法:
第一个算法还好,复习了一下这个过程,然后一遍就敲出来了,和教材上的一模一样(就是我们自己印的那个教材),但是在加注释完注释的时候出现问题了,我找了好一会,又是debug又是单步调试,但是都找不出来错误,最后我发现是我递归的边界没写好。例如,在这个算法中,如果所有的磁道都访问完之后,我原本写的程序没有跳出递归这一步操作,所以程序会输出一些垃圾数,甚至有的时候会导致程序崩溃,最后我加上跳出的那一步操作后就没问题,这里可以参考一下我的原代码,即没有加注释和改错之前的代码(代码查看地址:https://blog.csdn.net/qq_34035720/article/details/110494677  里面我详细写了每个代码的更改过程 包括原代码和注释更改后的最终代码)
CSCAN算法:
这个算法我感觉就更简单了,就是单纯的模拟这个过程,从大到小和从小到大,4for循环就ok了,但是正如我上面说的那样,我发现一个坑,这个坑是在从大到小的过程中,同时当前磁道号就等于访盘序列中某一个磁盘号时,会出现错误,原因是我用flag标记第一个大于等于当前磁道号的时候,因为是大于等于,所以可能会出现等于的情况,这样我从大到小跑的时候会忽略掉那个等于的部分,具体可以看我博客里写的原代码和最终代码的比较(网址在上面提到过),测试数据的话就是这个算法的样例2,如果用我的原代码和最终版代码跑一遍的话就会发现,两种代码输出的结果不一样,显然最终版是对的,所以我做了改动,里面用了三目运算符,感觉还挺好用的。

参考文献:
山东理工大学19级计科(中外)操作系统教材———复印ppt版
没有参考网络和其他同学

感想、体会和收获:
和上次的银行家算法一样,在敲代码之前从教材上复习了一下磁盘调度算法的整个过程,在熟知了所有磁盘调度算法的方法后我才开始敲代码,然后敲代码的过程总的来说还是挺顺利的,虽然中间出了一些小差错,但是最后都能改正过来。这个过程不仅让我学习了操作系统的相关知识,也让我提高了敲代码的能力,个人还是挺喜欢大作业的这种形式。
  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值