源码地址:https://github.com/duchenlong/linux-text/tree/master/disk
磁盘调度算法
先进先服务算法(FCFS)
该算法思想简单,不论初始磁头在什么位置,都是按照服务队列的先后顺序依次处理进程,可以类比队列的先进先出。
算法优点:进程处理起来非常简单,并且服务请求公平
缺点:系统平均寻道长度会很长,相临两次请求可能会造成最内到最外的柱面寻道,使磁头反复移动,增加了服务时间,对机械也不利
#include <vector>
#include <algorithm>
using namespace std;
class FCFS{
public:
FCFS(int start,vector<int> vec)
:_vec(vec)
{
_start = start;
}
int slove(int pos) {
int ret = abs(_vec[pos] - _start);
_start = _vec[pos];
return ret;
}
private:
vector<int> _vec;
int _start;
};
最短寻道时间优先(SSFT)
该算法本质是贪心算法。已知磁头的初始位置,则最先被处理就是距离磁头位置最近的进程,处理完成后再处理距离当前磁道最近的进程,直到所有的进程被处理。
算法优点:平均寻道长度会大大减少
缺点:距离初始磁头较远的服务长期得不到处理,产生“饥饿”现象。
具体的思路是:通过循环寻找与初始磁头最近的进程,将进程处理,然后将该进程标记为-1,将初始磁头移动到该进程所在的磁道。然后依次类推,标记为-1的进程不再参与,知道所有的进程都被标记为-1,磁盘调度完成
#include <vector>
#include <algorithm>
using namespace std;
class SSFT {
public:
SSFT(vector<int>& vec,int start) {
_pos = start;
_vec = vec;
_vis = vector<bool> (_vec.size(),false);
}
int slove() {
int p = -1;
int span = 0x3f3f3f3f;
int n = _vec.size();
for(int i = 0; i < n; i++) {
if(_vis[i]) continue;
int t = abs(_vec[i] - _pos);
if(t < span) {
p = i;
span = t;
}
}
_vis[p] = true;
int ret = span;
_pos = _vec[p];
return ret;
}
private:
vector<int> _vec;
vector<bool> _vis;
int _pos;
};
扫描算法(SCAN),又称电梯算法
磁头仅沿一个方向进行扫描,在扫描途中完成所有没有完成的请求,直到磁头到达磁盘在这个方向上的最后一个磁道或者这个方向上最后一个请求所在的磁道。
利用数组存储进程和磁道编号,依据给定的初始磁头,先找到初始磁头在哪两个进程之间,然后向内扫描。
当磁头扫描到磁盘最内层即磁道О且进程还没有全部被处理,磁头开始向外扫描,直到所有的进程都完成
单向扫描(CSCAN)
在磁盘扫描算法的基础上改变磁头的扫描路径:扫描到最内层之后从最外层向内继续扫描,即扫描方向一致。
该算法的思路与扫描算法基本一致,也使用二维数组进行进程编号和进程所在磁道号的存储,算法的不同之处在于当磁头扫描到磁盘的最内层时,磁头跳转到磁盘最外层重新向内扫描,这样就可以有效的避免将已经扫描过的磁道重新扫描一次,降低了平均寻到距离
#include <vector>
#include <unordered_set>
#include <algorithm>
using namespace std;
class SCAN{
public:
SCAN(int start,bool flag,vector<int>& vec) {
_pos = start;
_flag = flag;
_add = 1;
_min = *min_element(vec.begin(),vec.end());
_max = *max_element(vec.begin(),vec.end());
for(auto& e : vec) {
_hash.insert(e);
}
}
int slove() {
int ret = 0;
while(!_hash.empty()) {
if(_pos > _max) {
if(_flag) {
ret += _max - _min - 1;
_pos = _min;
}
else {
_add = -1;
_pos = _max - 1;
}
}
if(_hash.count(_pos) == 0) {
_pos+=_add;
ret++;
continue;
}
_hash.erase(_pos);
break;
}
return ret;
}
private:
bool _flag;
unordered_set<int> _hash;
int _pos;
int _add;
int _min;
int _max;
};