### 操作系统实验-磁盘调度:先来先服务、最短寻道时间算法
#### 实验背景
在操作系统中,磁盘调度是一项重要的技术,它直接影响到系统的响应时间和效率。磁盘作为存储设备,其读写操作的速度相对较低,因此通过合理的调度策略可以有效地减少磁盘寻道时间,从而提高整体性能。本实验将重点介绍两种常见的磁盘调度算法——先来先服务(FCFS)和最短寻道时间优先(SSTF),并通过编程模拟这两种算法。
#### 实验目的
1. **理解并掌握先来先服务(FCFS)算法:**了解FCFS算法的基本思想及其工作方式,并能够分析其优点和局限性。
2. **理解并掌握最短寻道时间(SSTF)算法:**熟悉SSTF算法的工作机制,能够对其性能特点进行评价。
#### 实验原理
**先来先服务(FCFS)算法**
- **定义:**FCFS算法按照进程请求访问磁盘的顺序进行调度。即,最先请求磁盘访问的进程首先得到服务。
- **优点:**公平、简单,每个请求都按顺序得到处理,避免了某些进程请求长时间得不到满足的情况。
- **缺点:**由于没有对寻道进行优化,可能会导致较高的平均寻道时间,特别是当请求分布较分散时。
**最短寻道时间(SSTF)算法**
- **定义:**SSTF算法总是选择与当前磁头所在位置距离最近的磁道进行访问,以实现最短的寻道时间。
- **优点:**通过减少单次寻道的时间,理论上可以降低平均寻道时间。
- **缺点:**可能会导致“饥饿”问题,即某些磁道的请求可能长期得不到处理,特别是在磁盘两端频繁切换的情况下。
#### 实验内容
**模拟实现**
实验要求通过编程模拟两种磁盘调度算法。为了实现这一目标,实验采用了以下数据结构和变量:
- **数据结构定义:**
```c
typedef struct Track {
int Track_ID; // 磁道号
int Track_State; // 磁道标志,未被访问置为0
} Track;
```
- **全局变量声明:**
- `Track track[N];` // 最大磁道数N为100
- `Track trackOut[N];`
- `int Distance[N];` // 移动距离
- `int Track_Num;` // 需访问的磁道数目
- `int Current_Track;` // 当前磁道
- `int TrackBackup;` // 存放初始磁道位置
**算法流程**
1. **先来先服务算法流程:**
- 初始化所有磁道状态为未访问。
- 对每个请求,计算当前磁道与目标磁道之间的距离。
- 将当前磁道设置为目标磁道,并更新磁道状态。
- 重复直到所有请求都被处理完毕。
2. **最短寻道时间优先算法流程:**
- 初始化所有磁道状态为未访问。
- 查找离当前磁道最近的磁道。
- 更新当前磁道为找到的磁道,并将其状态设置为已访问。
- 重复步骤2-3直到所有磁道都被访问过。
#### 程序代码
下面给出了一个简化的C语言程序框架,用于实现FCFS和SSTF算法。
```c
#include <stdio.h>
#include <stdlib.h>
#define N 100
typedef struct Track {
int Track_ID; // 磁道号
int Track_State; // 磁道标志,未被访问置为0
} Track;
Track track[N]; // 最大磁道数为100
Track trackOut[N];
int Distance[N]; // 移动距离
int Track_Num; // 需访问的磁道数目
int Current_Track; // 当前磁道
int TrackBackup; // 存放初始磁道位置
void init() { // 初始化
for (int i = 0; i < Track_Num; i++) {
track[i].Track_State = 0;
trackOut[i].Track_State = 0;
Distance[i] = 0;
}
}
void Input() { // 输入函数
printf("输入当前磁道:");
scanf("%d", &Current_Track);
TrackBackup = Current_Track;
printf("输入访问的磁道数目:");
scanf("%d", &Track_Num);
if (Track_Num > N) {
printf("输入错误:要访问的磁道数目大于最大值。\n");
return;
}
for (int i = 0; i < Track_Num; i++) {
printf("输入第%d个要访问的磁道号:", i + 1);
scanf("%d", &track[i].Track_ID);
}
system("cls"); // 刷新控制台
}
int abs(int a, int b) { // 求a-b的绝对值
return a - b >= 0 ? a - b : b - a;
}
void FCFS() { // 先来先服务算法
for (int i = 0; i < Track_Num; i++) {
Distance[i] = abs(Current_Track, track[i].Track_ID); // 计算当前磁道与目标磁道的移动距离
track[i].Track_State = 1; // 状态置为1,视为已经访问过
Current_Track = track[i].Track_ID; // 更新当前磁道
}
}
int Search_min_pos() { // 寻找到当前磁道最短的需求磁道
int min = 45536; // 最小距离标志
int pos;
for (int i = 0; i < Track_Num; i++)
if (track[i].Track_State == 1) // 如果当前磁道已经访问过则跳过
continue;
else if (min > abs(track[i].Track_ID, Current_Track)) { // 寻找要访问的磁道与当前磁头所在的磁道的距离最近
min = abs(track[i].Track_ID, Current_Track);
pos = i;
}
track[pos].Track_State = 1; // 标记该磁道已被访问过
return pos; // 返回的位置
}
void SSTF() { // 最短寻道优先算法
while (1) {
int pos = Search_min_pos();
if (pos == -1) break;
Distance[pos] = abs(Current_Track, track[pos].Track_ID);
Current_Track = track[pos].Track_ID;
}
}
int main() {
// 主程序
// 初始化、输入数据、调用算法函数等
return 0;
}
```
#### 结论
通过本实验的学习和实践,学生可以更深入地理解磁盘调度算法的工作原理,并能够通过编程模拟的方式直观地观察到不同算法的表现差异。先来先服务算法因其简单的逻辑和实现而易于理解和实现,但在实际应用中可能不如最短寻道时间优先算法高效。后者虽然在理论上有更好的性能表现,但由于其实现相对复杂,且有可能导致某些请求长期等待的问题,因此在实际应用中也需要谨慎考虑。