操作系统-磁盘调度算法(SCAN、CSCAN)

目录

一、前言

二、要求实现的功能

三、运行结果

 四、代码

总结


一、前言

该系统名称为:磁盘调度算法2,使用的是C++。

二、要求实现的功能

设计主界面以灵活选择某算法,且以下算法都要实现

1、扫描算法(SCAN)

2、循环扫描算法(CSCAN)

并求出每种算法的平均寻道长度

三、运行结果

手动输入测试样例:    初始时磁头位置:45

                                    磁道序列:55 58 39 18 90 160 150 38 184

主界面:

 选择SCAN算法并手动输入磁道

 选择磁道算法并让系统自动输入磁道

 选择CSCAN算法并手动输入磁道

 选择CSCAN算法并让系统自动输入磁道

四、代码

代码如下:

#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include <random>

using namespace std;
struct node
{
	int positon;//磁道位置
	int moved;//磁道与当前磁头的距离
	int visit;//磁道是否被访问过
}que[1010];//初始磁道序列

void surface();
void input();//输入函数
void output2();//输出函数
int dis(int a, int b);//两个磁道距离的绝对值
void SCAN();//扫描法
void CSCAN();//循环扫描法

int sig, start, direction;//算法选择标志,当前磁头位置,磁头移动方向
int num;//磁道数量
int order[1010];//磁头访问的磁道序列
int total;//磁头访问的总磁道数
const int isVis = 1;//该磁道被访问过
const int noVis = 0;//该磁道没被访问过
const int bigger = 1;//向磁头号增大方向移动
const int smaller = 0;//向磁头号减小方向移动
int num3[8]={33,59,13,77,123,170,160,185};
int a1;//选择自动输入还是手动输入

int main()
{
    string a="yes";
    while(a=="yes")
    {
        surface();
	//程序输入
	input();

	//选择算法
	switch (sig)
	{
		case 1:SCAN(); break;
		case 2:CSCAN(); break;
	}
        //程序输出
    	output2();
     	cout<<"\n是否重新选择算法(yes/no):";
    	cin>>a;
    }

	return 0;
}

void surface()
{
	printf("-------------------磁盘调度算法2-------------------\n");
	printf("---------------------------------------------------\n");
	printf("**********************功能菜单*********************\n\n");
	printf("                   1.扫描算法(SCAN)              \n\n");//每次将磁头按照电梯的方式朝一个方向移动,到顶点后按相反方向折回
	printf("                   2.循环扫描算法(CSCAN)          \n\n");
	printf("                   3.退出系统                      \n\n");
	printf("***************************************************\n");
	printf("---------------------------------------------------\n\n\n");

	printf("请输入您想要使用的功能:");
}
void input()
{
	//freopen("osin.txt", "r", stdin);
	//freopen("osout.txt", "w", stdout);
	cin >> sig;	//算法选择标志

	start = 0;
	total = 0;
	cout<<"请输入当前磁头位置:";
	cin >> start;//初始磁头位置
	cout<<"请输入磁头移动方向(磁头号增大方向为1,否则为2):";
	cin >> direction;//磁头移动方向

	num = 0;
	char c;

    cout<<"------------------\n";
	cout<<"选择输入磁道方式\n";
	cout<<"1.手动输入\n";
	cout<<"2.自动输入\n";
	cout<<"------------------\n";
	cout<<"请输入选择的方式:";
	cin>>a1;
	if(a1==1)
    {
        cout<<"\n请输入磁道序列:";
	    while (scanf("%d", &que[num].positon))//输入磁道序列
	{
		que[num].moved = 0;
		que[num].visit = noVis;
		num++;
		c = getchar();
		if (c == '\n')//遇到换行符则输入结束
		{
			break;
		}
		else if (c == ',')//遇到逗号则继续读取
		{
			continue;
		}
	}
    }
    else
    {
        cout<<"\n自动生成的磁道序列为:";
        while(num<=7)
        {
           // cout<<num3[num]+" ";
            que[num].positon=num3[num];
            que[num].visit = noVis;
            num++;
        }
       /* for(int i=0;i<=7;i++)
        {
            cout<<num3[i]+" ";
        }*/


    }
}

void output2()
{
	double sum;
    if(a1==2)
    {
        for(int i=0;i<=7;i++)
        {
            printf("%d ",num3[i]);
        }
    }
	if(sig==1)
	{
		cout<<"\n-----------SCAN-----------\n";
		printf("      (从%d磁道开始)\n",order[0]);
		cout<<"  下一磁道号    移动距离\n" ;
		for (int i = 1; i <= num; i++)//磁头移动经过的磁道序列
	{
		if (i != num)
		{
			printf("    %-10d     %-10d\n", order[i],abs(order[i]-order[i-1]));
		}
		else
		{
			printf("    %-10d     %-10d\n", order[i],abs(order[i]-order[i-1]));
		}

		sum=i;
	}
	printf("平均寻道长度:%.1lf\n", total/(sum));//磁头移动经过的总磁道数
	cout<<"-----------SCAN结束------------";
	}
	if(sig==2)
	{
		cout<<"\n-----------CSCAN----------\n";
		printf("      (从%d磁道开始)\n",order[0]);
		for (int i = 1; i <= num; i++)//磁头移动经过的磁道序列
	{
		if (i != num)
		{
			printf("    %-10d     %-10d\n", order[i],abs(order[i]-order[i-1]));
		}
		else
		{
			printf("    %-10d     %-10d\n", order[i],abs(order[i]-order[i-1]));
		}
		sum=i;
	}
     	printf("平均寻道长度:%.1lf\n", total/(sum));//磁头移动经过的总磁道数
     	cout<<"-----------CSCAN结束------------";
	}
}
int dis(int a, int b)
{
	return abs(a - b);
}

void SCAN()
{
	order[0] = start;
	//构造电梯
	int sorted[1010];
	for (int i = 0; i < num; i++)
	{
		sorted[i] = que[i].positon;
	}
	sort(sorted, sorted + num);

	//距当前磁头距离最短的磁道号
	int mini = 0;
	while (start >= sorted[mini])//统计出大于初始磁道号的刺刀个数
	{
		mini++;
	}

	//开始运行电梯
	int ans = 1;
	if (direction == bigger)//向磁头号增大方向移动
	{
		//电梯上升
		for (int i = mini; i < num; i++)
		{
			order[ans] = sorted[i];//order是将要访问的磁道序列
			ans++;
		}
		total += (sorted[num - 1] - start);
		//电梯下降
		for (int i = mini - 1; i >= 0; i--)
		{
			order[ans] = sorted[i];
			ans++;
		}
		total += (sorted[num - 1] - sorted[0]);
	}
	else//向磁头号减小方向移动
	{
		//电梯下降
		for (int i = mini - 1; i >= 0; i--)
		{
			order[ans] = sorted[i];
			ans++;
		}
		total += (start - sorted[0]);
		//电梯上升
		for (int i = mini; i < num; i++)
		{
			order[ans] = sorted[i];
			ans++;
		}
		total += (sorted[num - 1] - sorted[0]);
	}
}
void CSCAN()
{
	order[0] = start;
	//构造电梯
	int sorted[1010];
	for (int i = 0; i < num; i++)
	{
		sorted[i] = que[i].positon;
	}
	sort(sorted, sorted + num);

	//距当前磁头距离最短的磁道号
	int mini = 0;
	while (start > sorted[mini])
	{
		mini++;
	}

	//开始运行电梯
	int ans = 1;
	if (direction == bigger)//向磁头号增大方向移动
	{
		//电梯上升
		for (int i = mini; i < num; i++)
		{
			order[ans] = sorted[i];
			ans++;
		}
		//电梯循环
		for (int i = 0; i < mini; i++)
		{
			order[ans] = sorted[i];
			ans++;
		}
		//推导可得,total等于两端长度的两倍减去中间没有覆盖到的一段
		total += (2 * (sorted[num - 1] - sorted[0]) - (start - sorted[mini - 1]));
	}
	else//向磁头号减小方向移动
	{
		//电梯下降
		for (int i = mini - 1; i >= 0; i--)
		{
			order[ans] = sorted[i];
			ans++;
		}
		//电梯循环
		for (int i = num - 1; i >= mini; i--)
		{
			order[ans] = sorted[i];
			ans++;
		}
		//推导可得,total等于两端长度的两倍减去中间没有覆盖到的一段
		total += (2 * (sorted[num - 1] - sorted[0]) - (sorted[mini] - start));
	}
}

总结

本次课设题目是磁盘调度算法,使我更加理解了磁盘调度算法的全过程。要实现该算法首先要了解算法的过程,最短寻道算法(SSTF)就是总会从等待访问者中挑选寻找时间最短的那个请求先执行的,无论是在磁盘的里面还是外面,只要离他近的就先执行。而循环扫描算法就和我们平时坐的电梯有点类似,先往一个方向运行。这次的实验里对总道数的计算一开始理解的不够全,尤其是循环扫描算法,但用电梯实例来想象模拟后我很快弄明白了怎么回事。

但是程序仍然有很多改进的地方,资源可以更加节约,算法也还有优化的余地,但是时间和精力有限,我会在课余的时间加深对磁盘调度的理解同时加上其他的算法,例如扫描调度(SCAN)算法,先来先服务(FCFS)等。这次实验也让我感觉到了算法才是程序的灵魂,没有好的算法就像巧妇难为无米之炊,即使有再好的工具和基本功,没有算法和基本思想也是不可行的。

通过实现磁盘调度算法的动态实现过程,让我更加清楚了算法的流程,非常深刻地了解了这几种调度算法的异同以及优缺点。不仅仅是上述四种调度算法,由于时间原因,没能实现C-LOOK调度算法。等有时间,我会亲自实现一遍C-LOOK算法,更加深入的了解磁盘调度算法的实际应用。

要深入理解并实现FCFS、SSTF、SCANCSCAN这四种磁盘调度算法,首先需要掌握每种算法的基本原理和实现方法。通过参考《C语言实现FCFS/SSTF/SCAN/CSCAN磁盘调度算法教程》,你将能够获得详细的实现指导和示例代码。 参考资源链接:[C语言实现FCFS/SSTF/SCAN/CSCAN磁盘调度算法教程](https://wenku.csdn.net/doc/5748i3fbfh?spm=1055.2569.3001.10343) FCFS(先来先服务)算法的基本原理是按照请求到达的顺序对磁盘进行服务。在C语言中,你可以使用队列数据结构来管理请求的顺序。 SSTF(最短寻道时间优先)算法则选择与当前磁头位置距离最近的请求进行服务。在C语言实现时,你可以计算当前磁头位置与每个请求的距离,并选择距离最近的请求进行服务。 SCAN(扫描)算法模拟电梯操作方式,从一个方向开始扫描直到最后一个请求或磁盘边缘,然后改变方向。C语言实现时,需要考虑磁头移动方向的改变以及如何选择路径上最近的请求。 CSCAN(循环扫描)是SCAN的变种,当到达一端后,磁头立即跳到另一端继续扫描。在C语言中,这需要特别处理磁头的“跳跃”逻辑,以及如何在两端循环服务请求。 实现这些算法后,可以通过模拟不同的请求序列来测试和比较它们的性能。你可以设计一系列测试用例,记录并分析每种算法的寻道时间、响应时间和吞吐量等性能指标,从而评估它们在不同场景下的表现。 完成这一项目,你不仅能够掌握磁盘调度算法的原理和C语言实现方法,还能够进行性能比较,为选择最佳的磁盘调度策略提供依据。因此,强烈建议你参考《C语言实现FCFS/SSTF/SCAN/CSCAN磁盘调度算法教程》,这将帮助你全面地理解这些算法,并通过实际编程实践提升你的系统设计能力。 参考资源链接:[C语言实现FCFS/SSTF/SCAN/CSCAN磁盘调度算法教程](https://wenku.csdn.net/doc/5748i3fbfh?spm=1055.2569.3001.10343)
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值