一、实验目的
1、了解磁盘结构以及磁盘上数据的组织方式;
2、掌握磁盘访问时间的计算方式;
3、掌握常用磁盘调度算法及其相关特性。
二、基本原理
FIFO:按访问请求到达的先后次序进行调度。
SSTF:优先选择使磁头臂从当前位置开始移动最少的磁盘I/O请求进行调度。
SCAN:要求磁头臂先沿一个方向移动,并在途中满足所有未完成的请求,直到它到达这个方向上的最后一个磁道,或者在这个方向上没有别的请求为止,后一种改进有时候称作LOOK策略。然后倒转服务方向,沿相反方向扫描,同样按顺序完成所有请求。
C-SCAN:在磁盘调度时,把扫描限定在一个方向,当沿某个方向访问到最后一个磁道时,磁头臂返回到磁盘的另一端,并再次开始扫描。
三、模块介绍
1、main()函数模块:初始化磁道序号和初始磁针位置并提供选择列表;
2、FIFO()函数模块:先进先出调度算法;
3、SSTF()函数模块:最短服务时间优先调度算法;
4、SCAN()函数模块:扫描(电梯)调度算法;
5、C-SCAN()函数模块:循环扫描调度算法。
四、流程图
五、代码实现
#include<iostream>
#include<cmath>
#include<algorithm>
#define MAXTRACK 1000
using namespace std;
int TRACK[MAXTRACK]; //初始磁道序列
int track[MAXTRACK]; //排序后的磁道序列
int start; //初始磁针位置
int tracknumber = 0; //磁道总数
int location; //初始磁针当前(下一个)位置的下标
double length; //总寻道长度
void FIFO(int TRACK[], int tracknumber, int start) {
double length = 0;
cout<<"Initial track position:" << start << endl;
for(int i = 0; i < tracknumber; i++) {
length += abs(TRACK[i] - start); //按初始顺序将长度累加
cout << "The track number of the next access is:" << TRACK[i] << endl;
cout << "The length of the seek is:" << abs(TRACK[i] - start) << endl;
start = TRACK[i]; //移动磁针位置
}
cout << "The average seek length is:" << length / tracknumber << endl;
}
void SSTF(int TRACK[], int tracknumber, int start) {
int left, right; //left:左移"指针";right:右移"指针"
bool flag; //false:左移"指针"到达边界;true: 右移"指针"到达边界
length = 0;
for(int i = 0; i < tracknumber; i++)
track[i] = TRACK[i];
sort(track, track + tracknumber);
if(start >= track[tracknumber - 1]) { //初始磁针位置比所有访问位置都大
for(int i = tracknumber - 1; i >= 0; i--) {
length += start - track[i];
cout << "The track number of the next access is:" << track[i] << endl;
cout << "The length of the seek is:" << abs(track[i] - start) << endl;
start = track[i];
}
}
else if(start <= track[0]) { //初始磁针位置比所有访问位置都小
for(int i = 0; i < tracknumber; i++) {
length += track[i] - start;
cout << "The track number of the next access is:" << track[i] << endl;
cout << "The length of the seek is:" << abs(track[i] - start) << endl;
start = track[i];
}
}
else { //初始磁针位置在访问区域中
for(int i = 1; i < tracknumber; i++)
if(start > track[i - 1] && start <= track[i])
location = i; //定位磁针
left = location - 1;
right = location;
while(true) {
if(abs(start - track[left]) >= abs(start - track[right])) {
length += abs(start - track[right]); //右侧更近
cout << "The track number of the next access is:" << track[right] << endl;
cout << "The length of the seek is:" << abs(track[right] - start) << endl;
start = track[right];
if(right == tracknumber - 1) { //到达右边界
flag = true;
break;
}
right++;
}
else {
length += abs(start - track[left]); //左侧更近
cout << "The track number of the next access is:" << track[left] << endl;
cout << "The length of the seek is:" << abs(track[left] - start) << endl;
start = track[left];
if(left == 0) { //到达左边界
flag = false;
break;
}
left--;
}
}
if(flag) { //左移"指针"一直左移
while(true) {
if(left == 0) {
length += abs(start - track[left]);
cout << "The track number of the next access is:" << track[left] << endl;
cout << "The length of the seek is:" << abs(track[left] - start) << endl;
break;
}
else {
length += abs(start - track[left]);
cout << "The track number of the next access is:" << track[left] << endl;
cout << "The length of the seek is:" << abs(track[left] - start) << endl;
start = track[left--];
}
}
}
else { //右移"指针"一直右移
while(true) {
if(right == tracknumber-1) {
length += abs(start - track[right]);
cout << "The track number of the next access is:" << track[right] << endl;
cout << "The length of the seek is:" << abs(track[right] - start) << endl;
break;
}
else {
length += abs(start - track[right]);
cout << "The track number of the next access is:" << track[right] << endl;
cout << "The length of the seek is:" << abs(track[right] - start) << endl;
start = track[right++];
}
}
}
}
cout << "The average seek length is:" << length / tracknumber << endl;
}
void SCAN(int TRACK[], int tracknumber, int start) {
bool flag; //false:优先向左移动;true:优先向右移动
length = 0;
for(int i = 0; i < tracknumber; i++)
track[i] = TRACK[i];
sort(track, track + tracknumber);
for(int i = 1; i < tracknumber; i++) {
if(start > track[i - 1] && start <= track[i]) {
location = i; //定位磁针
if(abs(track[i] - start) > abs(track[i - 1] - start)) flag = false;
else flag = true;
break; //确定磁针距离最近的两端磁道中更近的磁道所在方向
}
}
if(!flag) { //先左移
for(int i = location - 1; i >= 0; i--) {
length += abs(start - track[i]);
cout << "The track number of the next access is:" << track[i] << endl;
cout << "The length of the seek is:" << abs(track[i] - start) << endl;
start = track[i];
}
for(int i = location; i < tracknumber; i++) { //调转方向
length += abs(start - track[i]);
cout << "The track number of the next access is:" << track[i] << endl;
cout << "The length of the seek is:" << abs(track[i] - start) << endl;
start = track[i];
}
}
else { //先右移
for(int i = location; i < tracknumber; i++) {
length += abs(start - track[i]);
cout << "The track number of the next access is:" << track[i] << endl;
cout << "The length of the seek is:" << abs(track[i] - start) << endl;
start = track[i];
}
for(int i = location - 1; i >= 0; i--) { //调转方向
length += abs(start-track[i]);
cout << "The track number of the next access is:" << track[i] << endl;
cout << "The length of the seek is:" << abs(track[i] - start) << endl;
start = track[i];
}
}
cout << "The average seek length is:" << length / tracknumber << endl;
}
void C_SCAN(int TRACK[], int tracknumber, int start) {
bool flag; //false:优先向左移动;true:优先向右移动
length = 0;
for(int i = 0; i < tracknumber; i++)
track[i] = TRACK[i];
sort(track, track + tracknumber);
for(int i = 1; i < tracknumber; i++) {
if(start > track[i - 1] && start <= track[i]) {
location = i; //定位磁针
if(abs(track[i] - start) > abs(track[i - 1] - start)) flag = false;
else flag = true;
break; //确定磁针距离最近的两端磁道中更近的磁道所在方向
}
}
if(!flag) { //先左移
for(int i = location - 1; i >= 0; i--) {
length += abs(start - track[i]);
cout << "The track number of the next access is:" << track[i] << endl;
cout << "The length of the seek is:" << abs(track[i] - start) << endl;
start = track[i];
}
for(int i = tracknumber - 1 ; i >= location ; i--) {//从另一端继续
length += abs(start - track[i]);
cout << "The track number of the next access is:" << track[i] << endl;
cout << "The length of the seek is:" << abs(track[i] - start) << endl;
start = track[i];
}
}
else { //先右移
for(int i = location; i < tracknumber; i++) {
length += abs(start - track[i]);
cout << "The track number of the next access is:" << track[i] << endl;
cout << "The length of the seek is:" << abs(track[i] - start) << endl;
start = track[i];
}
for(int i = 0; i <= location - 1; i++) { //从另一端继续
length += abs(start-track[i]);
cout << "The track number of the next access is:" << track[i] << endl;
cout << "The length of the seek is:" << abs(track[i] - start) << endl;
start = track[i];
}
}
cout << "The average seek length is:" << length / tracknumber << endl;
}
int main(void) {
int choice;
cout << "****************磁盘调度算法****************" << endl;
cout << "Please enter the track number to access (1-1000, enter -1 to stop input):" << endl;
while (true) { //输入访问的磁道序号
cin >> TRACK[tracknumber];
if (TRACK[tracknumber] == -1)
break;
else if(TRACK[tracknumber] > MAXTRACK || TRACK[tracknumber] < 0) {
cout << "Input error, please re-enter:" << endl;
continue;
}
tracknumber++;
}
for(int i = 0; i < tracknumber; i++)
track[i] = TRACK[i];
sort(track, track + tracknumber);
cout<<"Please enter the initial position of the magnetic needle : ";
cin >> start; //输入初始磁针位置
while(true) {
if(start < 0 || start > MAXTRACK) {
cout << "Input error, please re-enter:";
cin >> start;
}
else
break;
}
cout << "There are currently " << tracknumber << " tracks to access." << endl;
cout << "The sequence of the input track is:";
for(int i = 0; i < tracknumber; i++) {
if(i != tracknumber - 1)
cout << TRACK[i] << "->";
else
cout << TRACK[i] << endl;
}
cout << "The sorted track sequence is:";
for(int i = 0; i < tracknumber; i++) {
if(i != tracknumber - 1)
cout << track[i] << "->";
else
cout << track[i] << endl;
}
cout << "The initial position of the magnetic needle:" << start << endl;
while(true) {
cout << "1.FIFO" << endl;
cout << "2.SSTF" << endl;
cout << "3.SCAN" << endl;
cout << "4.C-SCAN" << endl;
cout << "Please select disk scheduling algorithm (Enter 0 to exit the program):";
cin >> choice;
if(choice >= 0 && choice <= 4) {
switch(choice) {
case 0:
exit(0);
case 1:
FIFO(TRACK, tracknumber, start);
break;
case 2:
SSTF(TRACK, tracknumber, start);
break;
case 3:
SCAN(TRACK, tracknumber, start);
break;
case 4:
C_SCAN(TRACK, tracknumber, start);
break;
}
}
else
cout << "Input error, please re-enter!" << endl;
}
}
六、实验结果与分析
1、FIFO
磁针从100开始,按照初始磁道序列进行扫描得出结果。
2、SSTF
先判断初始磁针位置与访问区间的相对位置,可知初始磁针位置在访问区间中,定位距离磁针最近的左右两个磁道的位置(90和150)并用指针标记,依次计算比较最近的两端磁道与磁针当前的距离,每次向更近的磁道方向扫描并移动该方向上的指针。本题数据左指针先到达边界(18),调转方向继续扫描,直到访问到右边界(184)时停止扫描,计算出结果。
3、SCAN
磁针从100开始先定位距离最近的两个磁道(90和150),确定更近的磁道方向(左侧)开始扫描,当扫描到左边界(18)时,调转方向继续扫描,直到扫描到右边界(184)时停止扫描,计算出结果。
4、C-SCAN
磁针从100开始先定位距离最近的两个磁道(90和150),确定更近的磁道方向(左侧)开始扫描,当扫描到左边界(18)时,从对侧(184)继续扫描,直到扫描到之前定位的右侧磁道(150)时停止扫描,计算出结果。