移动头磁盘调度算法模拟实现与比较

 代码仓库:JJLi0427/operationsystem (github.com)

1.实验目标

利用标准 C 语言,编程设计与实现关于移动头磁盘调度的先来先服务调度算法(FCFS)、最短寻道时间优先调度算法(SSTF)、电梯调度算法(SCAN)、循环式单向电梯调度算法(CSCAN)、双队列电梯调度算法(FSCAN),并随机发生一组磁盘访问事件(磁道号)序列开展有关算法的测试及性能比较。

2.五种移动头磁盘算法

  1. 先来先服务调度算法(FCFS):这是最简单的磁盘调度算法。它按照请求到达的顺序进行服务。这种方法公平且简单,但可能导致较长的平均寻道时间。
    int FCFS(vector<int> requests) {
        int times = 0;
        for (int i = 1; i < requests.size(); i++) {
            times += abs(requests[i] - requests[i - 1]);
        }
        return times;
    }
  2. 最短寻道时间优先调度算法(SSTF):这种算法选择距离当前磁头位置最近的请求进行服务。这种方法可以显著减少平均寻道时间,但可能导致远离磁头的请求等待时间过长,产生“饥饿”现象。
    int SSTF(vector<int> requests) {
        int times = 0;
        int size = requests.size();
        int curr = requests[0];
        requests.erase(requests.begin());
        while (!requests.empty()) {
            auto closest = min_element(requests.begin(), requests.end(),
                                       [curr](int a, int b) {
                                           return abs(a - curr) < abs(b - curr);
                                       });
            times += abs(*closest - curr);
            curr = *closest;
            requests.erase(closest);
        }
        return times;
    }
  3. 电梯调度算法(SCAN):这种算法让磁头像电梯一样运动,从一端移动到另一端,然后反向移动。这种方法公平且有效,因为它可以在两个方向上服务请求,避免了“饥饿”现象。
    int SCAN(vector<int> requests) {
        int times = 0;
        int size = requests.size();
        int curr = requests[0];
        requests.erase(requests.begin());
        sort(requests.begin(), requests.end());
        auto upper = upper_bound(requests.begin(), requests.end(), curr);
        if (upper != requests.end()) {
            for(auto it = upper; it != requests.end(); it++) {
                times += abs(*it - curr);
                curr = *it;
            }
        }
        if (upper != requests.begin()) {
            for(auto it = prev(upper); it != requests.begin(); it--) {
                times += abs(*it - curr);
                curr = *it;
            }
            times += abs(*requests.begin() - curr);
        }
        return times;
    }
  4. 循环式单向电梯调度算法(CSCAN):这种算法也让磁头像电梯一样运动,但当磁头到达一端时,它会立即返回到另一端,而不是反向移动。这种方法可以提供更均匀的等待时间。
    int CSCAN(vector<int> requests) {
        int times = 0;
        int size = requests.size();
        int curr = requests[0];
        requests.erase(requests.begin());
        sort(requests.begin(), requests.end());
        auto upper = upper_bound(requests.begin(), requests.end(), curr);
        if (upper != requests.end()) {
            for(auto it = upper; it != requests.end(); it++) {
                times += abs(*it - curr);
                curr = *it;
            }
        }
        if (upper != requests.begin()) {
            times += abs(*requests.begin() - curr);
            curr = *requests.begin();
            for(auto it = requests.begin(); it != upper; it++) {
                times += abs(*it - curr);
                curr = *it;
            }
        }
        return times;
    }
    
  5. 双队列电梯调度算法(FSCAN):这种算法类似于SCAN,但它维护了两个请求队列。当一个队列被服务时,新的请求被添加到另一个队列。这种方法可以避免因新请求的到达而导致磁头反向移动,从而提高效率。
    int FSCAN(vector<int> requests) {
        int times = 0;
        int que = 0;
        sort(requests.begin(), requests.end());
        vector<vector<int>> queues(2);
        int mid = requests.size() / 2;
        queues[0] = vector<int>(requests.begin(), requests.begin() + mid);
        queues[1] = vector<int>(requests.begin() + mid, requests.end());
        int curr = queues[que][0];
        queues[que].erase(queues[que].begin());
        while (!queues[0].empty() || !queues[1].empty()) {
            sort(queues[que].begin(), queues[que].end());
            while (!queues[que].empty()) {
                times += abs(queues[que].back() - curr);
                curr = queues[que].back();
                queues[que].pop_back();
            }
            que = 1 - que;
        }
        return times;
    }

3.模拟访问 

实现移动头磁盘访问事件序列的随机发生机制,其中所生成的磁道号取值 区间为[0, 199],基于相同的一组移动头磁盘访问事件序列(长度为 100,即 100 个磁道号),进行有关算法的测试。

实验模拟思路:模拟生成了一百次访问序列,每个访问序列都是一百个随机在0-199之间的元素,代表要访问的磁道。在进行了一百次测试之后输出平均的寻道时间。

4.主函数实现 

#include <iostream>
#include <vector>
#include <algorithm>
#include <cstdlib>
#include <ctime>

using namespace std;

int main() {
    srand(time(0));
    int totalFCFS = 0, totalSSTF = 0, totalSCAN = 0, totalCSCAN = 0, totalFSCAN = 0;
    for (int i = 0; i < 100; i++) {
        vector<int> requests(100);
        for (int j = 0; j < requests.size(); j++) requests[j] = rand() % 200;
        totalFCFS += FCFS(requests);
        totalSSTF += SSTF(requests);
        totalSCAN += SCAN(requests);
        totalCSCAN += CSCAN(requests);
        totalFSCAN += FSCAN(requests);
    }
    cout << "FCFS average seek time:  " << totalFCFS / 100.0 << endl;
    cout << "SSTF average seek time:  " << totalSSTF / 100.0 << endl;
    cout << "SCAN average seek time:  " << totalSCAN / 100.0 << endl;
    cout << "CSCAN average seek time: " << totalCSCAN / 100.0 << endl;
    cout << "FSCAN average seek time: " << totalFSCAN / 100.0 << endl;
    return 0;
}

5.运行结果

  • 21
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

哆啦叮当

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值