磁盘调度算法及其应用

news2025/2/23 18:12:08

导读:

磁盘调度是计算机系统中的重要问题之一。在多个进程同时访问磁盘时,合理的磁盘调度算法可以优化磁盘访问顺序,提高系统性能。本文将介绍磁盘调度算法的基本思想,并通过一个实验来模拟不同调度算法的运行过程。

正文:

在计算机系统中,磁盘是一种高速、大容量、可直接存取的存储设备,常用作辅助存储器。然而,由于磁盘的物理结构和工作原理,磁盘访问时间主要受寻道时间的影响,因此合理的磁盘调度算法对于降低寻道时间、提高系统性能非常重要。

本篇博客模拟设计一个磁盘调度程序,观察不同调度算法的动态运行过程,并比较它们的性能。实验内容包括四种磁盘调度算法:先来先服务调度算法(FCFS)、最短寻道时间优先算法(SSTF)、扫描算法(SCAN)和循环扫描算法(C-SCAN)。通过计算移动的总磁道数和平均寻道长度,评估各算法的效果。

在实验过程中,我们采用了一组测试数据,包括磁盘读写请求队列和当前磁头位置。首先,我们针对每种算法编写了相应的代码,并按照流程图进行实现。代码中使用了冒泡排序法对磁道号进行递增排序,以便后续的调度操作。

先来先服务调度算法(FCFS)是最简单的调度算法之一。它按照请求的先后顺序进行调度,不考虑磁道的位置。在实验中,我们根据给定的磁道号队列和当前磁头位置,输出磁盘调度顺序,并计算移动的总磁道数和平均寻道长度。

最短寻道时间优先算法(SSTF)则根据当前磁头位置选择离它最近的磁道进行访问。在实验中,我们对磁道号进行递增排序后,根据当前磁头位置选择合适的方向进行访问,直到服务完所有请求。同样地,我们计算移动的总磁道数和平均寻道长度。
扫描算法(SCAN)是一种具有方向性的调度算法,它沿着磁道的一个方向移动,直到最后一个请求,然后改变方向返回,直到处理完所有请求。在实验中,我们首先确定磁头移动的方向,然后按照该方向顺序依次处理请求,直到所有请求完成。我们计算移动的总磁道数和平均寻道长度。

循环扫描算法(C-SCAN)是扫描算法的改进版本。它也是沿着一个方向移动,直到最后一个请求,然后立即返回到最开始的磁道,继续按照相同的方向处理请求。在实验中,我们按照递增排序后的磁道号顺序处理请求,计算移动的总磁道数和平均寻道长度。

完整代码:

#include <stdio.h>
#include <math.h>
#include <stdlib.h>

// 先来先服务调度算法(FCFS)
void FCFS(int a[], int n) {
	int sum = 0, i, now;
	float ave;

	printf("请输入当前的磁道号: ");
	scanf("%d", &now);
	printf("磁盘调度顺序为:\n");
	for (i = 1; i < n; i++) {
		printf("%d ", a[i]); // 按访问顺序输出磁道号
	}
	for (i = 0; i < n - 1; i++) {
		sum += abs(a[i + 1] - a[i]); // 计算移动的总磁道数,abs取绝对值
	}
	ave = (float)(sum) / (n - 1); // 求平均寻道长度

	printf("\n");
	printf("移动的总磁道数:%d\n", sum);
	printf("平均寻道长度:%.2f\n", ave);
}

// 最短寻道时间优先算法(SSTF)
void SSTF(int a[], int n) {
	int temp; // 中间变量
	int k = 1;
	int now, l, r;
	int i, j, sum = 0;
	float ave;

	// 将磁道号按递增排序(冒泡排序法)
	for (i = 0; i < n; i++) {
		for (j = i + 1; j < n; j++) {
			if (a[i] > a[j]) {
				temp = a[i];
				a[i] = a[j];
				a[j] = temp;
			}
		}
	}

	printf("按递增顺序排好的磁道号依次为:\n");
	for (i = 0; i < n; i++) {
		printf("%d ", a[i]);
	}
	printf("\n");
	printf("请输入当前的磁道号:");
	scanf("%d", &now); // 确定当前磁头所在位置
	printf("磁盘扫描顺序为:\n");

	if (a[n - 1] == now) { // 当前磁道号是请求序列中最大者,则直接由外向内依次给予各请求服务
		for (i = n - 1; i >= 0; i--) {
			sum = now - a[0];
			printf("%d ", a[i]);
		}
	} else if (a[0] == now) { // 当前磁道号是请求序列中最小者,则直接由内向外依次给予各请求服务
		for (i = 0; i < n; i++) {
			printf("%d ", a[i]);
		}
		sum = a[n - 1] - now;
	} else if (now > a[0] && now < a[n - 1]) { // 若当前磁道号在最大与最小磁道号之间
		// 找到当前磁道号右边的磁道
		for (i = 0; i < n; i++) {
			if (a[i] > now) {
				k = i;
				break;
			}
		}
		l = k - 1; // 左边磁道索引
		r = k; // 右边磁道索引

		while (l >= 0 && r < n) {
			if (now - a[l] <= a[r] - now) {
				printf("%d ", a[l]);
				sum += now - a[l];
				now = a[l];
				l--;
			} else {
				printf("%d ", a[r]);
				sum += a[r] - now;
				now = a[r];
				r++;
			}
		}

		if (l < 0) {
			while (r < n) {
				printf("%d ", a[r]);
				sum += a[r] - now;
				now = a[r];
				r++;
			}
		} else if (r >= n) {
			while (l >= 0) {
				printf("%d ", a[l]);
				sum += now - a[l];
				now = a[l];
				l--;
			}
		}
	}

	ave = (float)sum / n; // 计算平均寻道长度

	printf("\n");
	printf("移动的总磁道数:%d\n", sum);
	printf("平均寻道长度:%.2f\n", ave);
}

// 扫描算法(SCAN)
void SCAN(int a[], int n) {
	int temp; // 中间变量
	int k = 1;
	int now, l, r;
	int i, j, sum = 0;
	float ave;

	// 将磁道号按递增排序(冒泡排序法)
	for (i = 0; i < n; i++) {
		for (j = i + 1; j < n; j++) {
			if (a[i] > a[j]) {
				temp = a[i];
				a[i] = a[j];
				a[j] = temp;
			}
		}
	}

	printf("按递增顺序排好的磁道号依次为:\n");
	for (i = 0; i < n; i++) {
		printf("%d ", a[i]);
	}
	printf("\n");
	printf("请输入当前的磁道号:");
	scanf("%d", &now); // 确定当前磁头所在位置
	printf("磁盘扫描顺序为:\n");

	if (a[n - 1] == now) { // 当前磁道号是请求序列中最大者,则直接由外向内依次给予各请求服务
		for (i = n - 1; i >= 0; i--) {
			printf("%d ", a[i]);
			sum += now - a[i];
			now = a[i];
		}
	} else if (a[0] == now) { // 当前磁道号是请求序列中最小者,则直接由内向外依次给予各请求服务
		for (i = 0; i < n; i++) {
			printf("%d ", a[i]);
			sum += a[i] - now;
			now = a[i];
		}
	} else if (now > a[0] && now < a[n - 1]) { // 若当前磁道号在最大与最小磁道号之间
		// 找到当前磁道号右边的磁道
		for (i = 0; i < n; i++) {
			if (a[i] > now) {
				k = i;
				break;
			}
		}
		l = k - 1; // 左边磁道索引
		r = k; // 右边磁道索引

		while (l >= 0 && r < n) {
			printf("%d ", a[r]);
			sum += a[r] - now;
			now = a[r];
			r++;
		}

		if (l < 0) {
			while (r < n) {
				printf("%d ", a[r]);
				sum += a[r] - now;
				now = a[r];
				r++;
			}
		} else if (r >= n) {
			while (l >= 0) {
				printf("%d ", a[l]);
				sum += now - a[l];
				now = a[l];
				l--;
			}
		}
	}

	ave = (float)sum / n; // 计算平均寻道长度

	printf("\n");
	printf("移动的总磁道数:%d\n", sum);
	printf("平均寻道长度:%.2f\n", ave);
}

// 循环扫描算法(C-SCAN)
void CSCAN(int a[], int n) {
	int temp; // 中间变量
	int k = 1;
	int now, l, r;
	int i, j, sum = 0;
	float ave;

	// 将磁道号按递增排序(冒泡排序法)
	for (i = 0; i < n; i++) {
		for (j = i + 1; j < n; j++) {
			if (a[i] > a[j]) {
				temp = a[i];
				a[i] = a[j];
				a[j] = temp;
			}
		}
	}

	printf("按递增顺序排好的磁道号依次为:\n");
	for (i = 0; i < n; i++) {
		printf("%d ", a[i]);
	}
	printf("\n");
	printf("请输入当前的磁道号:");
	scanf("%d", &now); // 确定当前磁头所在位置
	printf("磁盘扫描顺序为:\n");

	if (a[n - 1] == now) { // 当前磁道号是请求序列中最大者,则直接由外向内依次给予各请求服务
		for (i = n - 1; i >= 0; i--) {
			printf("%d ", a[i]);
			sum += now - a[i];
			now = a[i];
		}
		for (i = 0; i < n; i++) {
			printf("%d ", a[i]);
			sum += a[i] - now;
			now = a[i];
		}
	} else if (a[0] == now) { // 当前磁道号是请求序列中最小者,则直接由内向外依次给予各请求服务
		for (i = 0; i < n; i++) {
			printf("%d ", a[i]);
			sum += a[i] - now;
			now = a[i];
		}
		for (i = n - 1; i >= 0; i--) {
			printf("%d ", a[i]);
			sum += now - a[i];
			now = a[i];
		}
	} else if (now > a[0] && now < a[n - 1]) { // 若当前磁道号在最大与最小磁道号之间
		// 找到当前磁道号右边的磁道
		for (i = 0; i < n; i++) {
			if (a[i] > now) {
				k = i;
				break;
			}
		}
		l = k - 1; // 左边磁道索引
		r = k; // 右边磁道索引

		while (l >= 0 && r < n) {
			printf("%d ", a[r]);
			sum += a[r] - now;
			now = a[r];
			r++;
		}

		if (l < 0) {
			printf("%d ", a[n - 1]); // 最右边的磁道
			sum += a[n - 1] - now;
			now = a[n - 1];
			for (i = n - 2; i >= 0; i--) {
				printf("%d ", a[i]);
				sum += now - a[i];
				now = a[i];
			}
		} else if (r >= n) {
			printf("%d ", a[0]); // 最左边的磁道
			sum += now - a[0];
			now = a[0];
			for (i = 1; i < n; i++) {
				printf("%d ", a[i]);
				sum += a[i] - now;
				now = a[i];
			}
		}
	}

	ave = (float)sum / n; // 计算平均寻道长度

	printf("\n");
	printf("移动的总磁道数:%d\n", sum);
	printf("平均寻道长度:%.2f\n", ave);
}

int main() {
	int n, i;
	int a[20];

	printf("请输入磁道请求数:");
	scanf("%d", &n);
	printf("请输入磁道号:");
	for (i = 0; i < n; i++) {
		scanf("%d", &a[i]);
	}

	printf("请选择磁盘调度算法:\n");
	printf("1. 先来先服务调度算法(FCFS)\n");
	printf("2. 最短寻道时间优先算法(SSTF)\n");
	printf("3. 扫描算法(SCAN)\n");
	printf("4. 循环扫描算法(C-SCAN)\n");
	int choice;
	printf("请输入选择的算法:");
	scanf("%d", &choice);

	switch (choice) {
		case 1:
			FCFS(a, n);
			break;
		case 2:
			SSTF(a, n);
			break;
		case 3:
			SCAN(a, n);
			break;
		case 4:
			CSCAN(a, n);
			break;
		default:
			printf("无效选择\n");
			break;
	}

	return 0;
}

流程图

image.png

结论

通过实验比较四种磁盘调度算法的性能,我们可以得出以下结论:

  • FCFS算法简单直接,但可能导致平均寻道长度较长,性能相对较低。
  • SSTF算法能够减少寻道时间,但可能导致部分请求长时间等待,存在饥饿现象。
  • SCAN算法和C-SCAN算法通过方向性移动可以较好地均衡请求的处理,减少饥饿现象,但可能导致移动的总磁道数较多。

需要注意的是,磁盘调度算法的选择应根据具体的应用场景和需求进行权衡。不同的算法可能适用于不同的场景,具体的选择需要综合考虑各种因素,如磁盘负载、请求队列的特征等。

总结起来,磁盘调度算法是优化磁盘访问顺序、提高系统性能的重要手段。通过实验和比较不同的算法,可以选择合适的磁盘调度策略。然而,随着技术的发展和硬件的进步,新的磁盘调度算法也在不断涌现,以应对不同场景下的需求。因此,磁盘调度算法的研究和优化仍然具有重要的意义。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/656248.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

如何翻译 Markdown 文件?-2-几种商业及开源解决方案介绍

背景 近期在搭建英文博客-<e-whisper.com>, 需要对现有的所有中文 Markdown 翻译为英文。 需求如下&#xff1a; 将 Markdown 文件从中文 (zh-CN) 翻译为英文 (en)翻译后要保留 Markdown 的完整格式部分 Markdown block 不需要翻译&#xff0c;如&#xff1a;front-ma…

电脑蓝屏问题

如何使用DISM命令行工具修复Windows 10映像 - 系统极客 (sysgeek.cn) 电脑每周基本都会出现一次蓝屏问题&#xff1a;THREAD_STUCK_IN_DEVICE_DRIVER 售后重装系统&#xff0c;换主板&#xff0c;换硬盘都没有用&#xff0c;实在是人麻了 不知道有没有用&#xff0c;先记录一…

“边玩边赚”的区块链游戏发展前景和趋势

2008年&#xff0c;一个真实的故事。 大学期间&#xff0c;睡在我下铺的兄弟没日没夜地玩一款电脑游戏——《热血江湖》&#xff0c;期末考试和考研都没能阻止他。而最终&#xff0c;是游戏里的一把枪让他改邪归正。因为他把那件装备卖给了一个北京人&#xff0c;价格高达3000…

IT专业相关介绍【活动】

IT专业相关介绍【活动】 前言IT专业相关介绍一、IT专业的就业前景和发展趋势二、了解IT专业的分类和方向三、你对本专业的看法和感想四、本专业对人能力素养的要求五、建议和思考六、计算机思维能力测试 最后 前言 2023-6-17 10:00:29 以下内容源自《【活动】》 仅供学习交流…

Spring-kafka的消费者模型和实现原理

在使用Spring-kafka时,一般都是通过使用@KafkaListener注解的方法来实现消息监听和消费。今天写一下基于这个注解实现的消费端模型和实现的原理。 Kafka消费模型 我们在使用@KafkaListener注解实现消费者时消费者模型是这样的: 每个@KafkaListener注解对应有一个Concurren…

python窗口程序button事件处理

import tkinter as tk def add_counter(): #增加计数print("add....")def zero_counter(): #归零计数print("zero....")#窗口的属性&#xff08;大小&#xff0c;&#xff09; root tk.Tk() root.geometry("400x200200200") root.title(&q…

亚马逊云科技中国峰会:深度学习Amazon DeepRacer

序言 Amazon DeepRacer是什么&#xff1f; Amazon DeepRacer是亚马逊推出的一款基于深度学习和强化学习技术的自主驾驶模拟赛车平台。它提供了一个云端仿真环境和一个物理赛车模型&#xff0c;让用户可以通过编写代码和训练模型来控制赛车的行驶&#xff0c;从而学习和应用深…

【LeetCode】HOT 100(14)

题单介绍&#xff1a; 精选 100 道力扣&#xff08;LeetCode&#xff09;上最热门的题目&#xff0c;适合初识算法与数据结构的新手和想要在短时间内高效提升的人&#xff0c;熟练掌握这 100 道题&#xff0c;你就已经具备了在代码世界通行的基本能力。 目录 题单介绍&#…

音视频开发Level0: 入门级20~25k的工作

今天给大家分享一个音视频开发领域&#xff0c;入门级别的工作&#xff0c;要求不高。 主要做什么呢&#xff0c;行车记录仪&#xff0c;运动相机&#xff0c;各种拍摄器材包括医疗领域的喉镜啊&#xff0c;等等。 这种产品&#xff0c;招人的公司深圳最多&#xff0c;因为深…

Mac 多版本jdk安装与切换

macOS上可以安装多个版本的jdk&#xff0c;方法如下&#xff1a; 1.下载jdk 在Oracle官网上下载不同版本的jdk&#xff1a; JDK下载 知乎 - 安全中心 下载Java11版本链接 jdk11​www.oracle.com/java/technologies/javase-jdk11-downloads.html 2.安装jdk 运行此安装包&…

electron-vue 安装 sqlite3 详细步骤

1 安装 Visual Studio 2019 使用 Visual Studio instaler 安装Visual Studio 2019&#xff0c; 安装桌面应用 使用c的桌面开发, 勾选 MSVC 相应的选项。 2. 安装 node 13 版本 可以根据自己实际情况安装版本 使用 cmd 管理员身份或者 powerShell 管理员身份 执行以下命令&…

骨传导蓝牙立体声耳机怎么选,列举几款值得购买的骨传导耳机

骨传导耳机的出现&#xff0c;使得很多人摆脱了佩戴入耳式耳机的困扰&#xff0c;同时也为骨传导耳机的发展起到了很大的推动作用。骨传导耳机是一种通过骨头传声的耳机&#xff0c;由于其不需要入耳&#xff0c;所以不会因为长时间佩戴而引起耳道的不适感&#xff0c;在使用时…

baichuan-7B: 开源可商用支持中英文的最好大模型

背景 baichuan-7B 是由百川智能开发的一个开源可商用的大规模预训练语言模型。 基于 Transformer 结构&#xff0c;在大约1.2万亿 tokens 上训练的70亿参数模型&#xff0c;支持中英双语&#xff0c;上下文窗口长度为4096。 在标准的中文和英文权威 benchmark&#xff08;C-…

【FreeRTOS】——列表与列表项列表相关API函数(初始化、插入、移除)

目录 前言&#xff1a; 一、列表与列表项 二、列表相关API函数 ①初始化列表vListInitialise() ②初始化列表项vListInitialise() ③列表插入列表项&#xff08;升序&#xff09;函数vListInsert() ④列表插入列表项&#xff08;无序&#xff09;函数vListInsertEnd() …

开源赋能 普惠未来——回顾全球数字经济大会及开放原子全球开源峰会(Intel专题)

一、峰会背景 2023年6月11日至13日&#xff0c;中国北京迎来了一场全球数字经济大会和开放原子全球开源峰会的盛会。这次大会在北京北人亦创国际会展中心隆重举行&#xff0c;为来自世界各地的数字经济和开源社区的代表们提供了一个共同交流、合作的平台。 本次大会以"开…

GAMES101笔记 Lecture02 线性代数基础

目录 A Swift and Brutal Introduction to Linear AlgebraGarphics Dependencies(图形学的依赖)Basic mathematics(基础的数学)Basic physics(基础的物理)Misc(杂项)And a bit of asethetics(以及一点美学) Vectors(向量)Vector Normalization(向量归一化)Vector Addition(向量…

记录好项目D7

记录好项目 你好呀&#xff0c;这里是我专门记录一下从某些地方收集起来的项目&#xff0c;对项目修改&#xff0c;进行添砖加瓦&#xff0c;变成自己的闪亮项目。修修补补也可以成为毕设哦 本次的项目是个酒店预订管理系统 技术栈&#xff1a;springbootjavamysqlmybatis …

从0到1学会在Linux中部署SpringBoot+Vue前后端分离项目

1.打包Vue前端项目 使用npm run build命令打包前端项目 前端项目会 打包到dist文件夹中 2.打包SpringBoot后端项目 点击生命周期的package命令&#xff0c;对后端项目进行打包 target目录下的renren-fast.jar就是刚刚打包的后端项目 后端打包项目有一个小技巧&#xff0c;就…

基于VUE3+Layui从头搭建通用后台管理系统(前端篇)一:项目规划及初始化

一、项目内容 使用vue3+Layui实现通用管理系统前端,使用vue3+layui搭建系统UI界面,使用nodejs搭建模拟web服务器,使用echarts实现系统可视化模块,可以此项目为基础进行扩展开发,快速搭建管理系统,具体内容如下:   1. 常见功能实现: 实现用户登录(用户名密码登录、手…

【c语言】 -- 详解数组篇

&#x1f4d5;博主介绍&#xff1a;目前大一正在学习c语言&#xff0c;数据结构&#xff0c;计算机网络。 c语言学习&#xff0c;是为了更好的学习其他的编程语言&#xff0c;C语言是母体语言&#xff0c;是人机交互接近底层的桥梁。 本章来学习数据的存储。 让我们开启c语言学…