磁盤調度 先來先服務(FCFS) 最短尋道時間優先(SSTF)
實驗內容:編寫一個程序處理磁盤調度中尋道時間的策略。
實驗目的:磁盤調度中尋道時間直接影響到數據訪問的快慢,處理好磁盤尋道時間是關鍵。
實驗題目:
- 采用先來先服務策略處理
- 采用最短尋道策略處理
https://github.com/SKPrimin/HomeWork/tree/main/OperatingSystem/diskpatch
實驗原理
先來先服務(FCFS)
優點:公平、簡單,每個進程的請求都能依次得到處理
缺點:未對尋道進行優化,平均尋道時間較長
流程圖
最短尋道時間優先(SSTF)
優點:平均每次磁頭移動距離較近;尋道性能比 FCFS 好,但不能保證尋道時間最短
缺點:不能保證平均尋道時間最短且有可能引起某些請求的飢餓
流程圖
實現
java
數據結構和符號說明
DiskDispatch為一個工具類,定義了僅有其子類能使用的
四個變量 start
為磁道開始點、track
為將要訪問的磁道號數組、distanceSum
移動距離總磁道數、movdistan
為將要計算的移動距離數組。
方法distance(int a, int b)
使用三元表達式計算出兩個磁盤的距離。
內部類Track
是自定義數據類型,內含磁道號和磁針調度到本磁道移動距離。
FCFS
類即先來先服務實現類
SSTF
類即最短尋道時間優先實現類
DiskDispatch磁盤公有類
package com.process.diskpatch;
import java.util.ArrayList;
/**
* @Author: SKPrimin
* @Date 2021/12/17 13:27
* @ClassName: DiskDispatch
* @Description: TODO
*/
public class DiskDispatch {
/**
* start為磁道開始點
* track為將要訪問的磁道號數組
* distanceSum移動距離總磁道數
* movdistan為將要計算的移動距離
*/
protected int start;
protected ArrayList<Integer> track;
protected int distanceSum = 0;
protected int[] movdistan;
/**
* 計算距離函數通過三元運算符返回兩數絕對值
*/
protected int distance(int a, int b) {
return a > b ? a - b : b - a;
}
/**
* 定義內部類 磁道類 包含磁道號 要想訪問須達到的距離
*/
static class Track {
int diskName;
int distance;
}
}
FCFS先來先服務實現類
package com.process.diskpatch;
import java.util.ArrayList;
import java.util.Arrays;
/**
* @Author: SKPrimin
* @Date 2021/12/16 23:12
* @ClassName: FCFS
* @Description: TODO 先來先服務磁盤調度算法
*/
public class FCFS extends DiskDispatch {
// 構造器
public FCFS(int start, ArrayList<Integer> track) {
this.start = start;
this.track = track;
movdistan = new int[track.size()];
}
/**
* 調度執行函數,進行此次先來先服務磁盤調度
*/
public void run() {
// 初始化磁針位置
int needle = start;
for (int i = 0; i < track.size(); i++) {
// 求出移動距離並保存
movdistan[i] = distance(needle, track.get(i));
distanceSum += movdistan[i];
// 更新指針位置
needle = track.get(i);
}
}
@Override
public String toString() {
return "\n先來先服務FCFS張丞E01914168" +
"\n從" + start + "號磁道開始" +
"\n被訪問的下一個磁道號\t" + track +
"\n移動距離(磁道數)\t" + Arrays.toString(movdistan) +
"\n總道數:"+distanceSum+"\t平均尋道長度:" + String.format("%.2f", (double) distanceSum / track.size());
}
}
SSTF最短尋道時間優先實現類
package com.process.diskpatch;
import java.util.ArrayList;
import java.util.Arrays;
/**
* @Author: SKPrimin
* @Date 2021/12/17 0:22
* @ClassName: SSTF
* @Description: TODO
*/
public class SSTF extends DiskDispatch {
/**
* trackSequence為SSTF調度的磁道號數組
* len 為傳出的磁道號數目
*/
private int[] trackSequence;
private int len;
// 構造器
public SSTF(int start, ArrayList<Integer> track) {
this.start = start;
this.track = track;
this.len = track.size();
movdistan = new int[len];
trackSequence = new int[len];
}
/**
* 調度執行函數,進行此次最短尋道時間優先磁盤調度
*/
public void run() {
// 初始化磁針位置
int needle = start;
for (int i = 0; i < len; i++) {
// 求出移動距離的磁道號以及移動距離
Track tc = shortest(needle, track);
// 將算出的將要訪問的下一磁道號、移動距離加入對應數組
trackSequence[i] = tc.diskName;
movdistan[i] = tc.distance;
distanceSum += movdistan[i];
// 更新指針位置以及磁道號列表,去除已經訪問的磁道號
needle = tc.diskName;
// 此處使用包裝類包裝,避免當成索引
track.remove(Integer.valueOf(tc.diskName));
}
}
/**
* 在給定范圍內找出里磁針最近的磁道號
*
* @param needle 磁針當前位置
* @param array 訪問磁道號數組,即查找范圍
* @return 查找到的要訪問的磁道號
*/
public Track shortest(int needle, ArrayList<Integer> array) {
// 各變量初始化 先默認第一個是距離最近的磁道
Track tc = new Track();
tc.diskName = array.get(0);
tc.distance = distance(needle, array.get(0));
// 進過遍歷,若發現有離得更近的就替換
for (int item :
array) {
if (distance(needle, item) < tc.distance) {
tc.diskName = item;
tc.distance = distance(needle, item);
}
}
return tc;
}
@Override
public String toString() {
return "\n最短尋道時間優先SSTF張丞E01914168" +
"\n從" + start + "號磁道開始" +
"\n被訪問的下一個磁道號\t" + Arrays.toString(trackSequence) +
"\n移動距離(磁道數)\t" + Arrays.toString(movdistan) +
"\n總道數:"+distanceSum+"\t平均尋道長度:" + String.format("%.2f", (double) distanceSum / len);
}
}
測試類
package com.process.diskpatch;
import java.util.ArrayList;
/**
* @Author: SKPrimin
* @Date 2021/12/17 0:20
* @ClassName: Test
* @Description: TODO 測試類 集中測試磁盤調度算法
*/
public class Test {
public static void main(String[] args) {
// 磁盤號順序
int[] track = new int[]{98, 183, 37, 122, 14, 124, 65, 67};
ArrayList<Integer> ta = new ArrayList<>();
for (int t : track) {
ta.add(t);
}
// 先來先服務
FCFS ff = new FCFS(53, ta);
ff.run();
System.out.println(ff);
//最短尋道時間優先
SSTF st = new SSTF(53, ta);
st.run();
System.out.println(st);
}
}
Python
def fifo(tracklist, needle):
movdistan = []
distanceSum = 0
print(f"\n先來先服務FCFS\n從{needle}號磁道開始")
print(f"被訪問的下一個磁道號\t移動距離(磁道數)")
for index, item in enumerate(tracklist):
# 算出移動距離並保存
movdistan.append(abs(needle - item))
distanceSum += movdistan[-1]
# 更新磁針位置
needle = item
print(f"\t{item}\t\t\t\t\t{movdistan[-1]}")
print(f"\n總道數:{distanceSum}\t平均尋道長度:{distanceSum / len(movdistan)}")
return movdistan, distanceSum
def sstf(tracklist, needle):
movdistan = []
trackSequence = []
distanceSum = 0
print(f"\n最短尋道時間優先SSTF\n從{needle}號磁道開始")
print(f"被訪問的下一個磁道號\t移動距離(磁道數)")
length = len(tracklist)
for i in range(length):
# 求出移動距離的磁道號以及移動距離
ts, distance = shortest(tracklist,needle )
trackSequence.append(ts)
movdistan.append(distance)
# 將算出的將要訪問的下一磁道號、移動距離加入對應數組
distanceSum += distance
# 更新指針位置以及磁道號列表,去除已經訪問的磁道號
needle = ts
tracklist.remove(ts)
print(f"\t{ts}\t\t\t\t\t{distance}")
print(f"\n總道數:{distanceSum}\t平均尋道長度:{distanceSum / len(movdistan)}")
def shortest(array,needle):
# 各變量初始化 先默認第一個是距離最近的磁道
diskName = array[0]
distance = abs(needle - array[0])
# 進過遍歷,若發現有離得更近的就替換
for item in array:
if abs(needle - item) < distance:
diskName = item
distance = abs(needle - item)
return diskName, distance
if __name__ == '__main__':
track = [55, 58, 39, 18, 90, 160, 150, 38, 184]
fifo(track, 100)
sstf(track, 100)