實驗要求
- 選擇1~3種磁盤調度算法(先來先服務法、最短尋道時間優先、電梯算法)模擬實現磁盤調度;
- 能夠輸入當前磁頭的位置、磁頭移動方向、磁道訪問請求序列等;
- 計算磁頭移動的總磁道數;
- 能夠顯示磁盤調度結果(磁頭依次訪問的磁道號順序等)
我選擇了先來先服務法FCFS、最短尋道時間優先SSTF、電梯算法SCAN三種調度算法,代碼用Java實現。
源碼已上傳到本人github上,建議先看源碼。
實驗原理
代碼結構
HardDrive類表示磁盤,其私有成員有tracks表示訪問序列數組,trackSet表示磁道訪問集合,用HashSet實現Set接口,headAt表示磁頭處於磁道位置,direction表示在SCAN調度算法裏磁頭移動的方向,distance表示磁頭移動的總距離,method表示調度方法
代碼思路
整體思路
用tracks數組表示訪問序列,用於FCFS調度。trackSet用於遍歷訪問序列,獲得每次離磁頭最近的磁道。headAt在每次移動磁頭後記錄位置,distance用來保存每次headAt移動前後距離的絕對值的累加和。
構造一個HardDrive對象,並將參數tracks、headAt、direction、method參數帶入,根據調度方法不同輸出不同的結果。
FCFS
先來先服務調度比較簡單,用數組表示順序訪問序列,遍歷數組,輸出下一個數組元素i,計算數組該元素i和當前headAt距離並保存到distance中,修改磁頭headAt位置。遍歷結束後輸出distance。
private void FCFS() {
System.out.print("尋道順序爲:" + headAt + " ");
for (int i : tracks) {
System.out.print(i + " ");
this.distance += Math.abs(headAt - i);
headAt = i;
}
System.out.println();
System.out.println("總路程=" + this.distance);
}
SSTF
最短尋道時間優先調度使用trackSet,遍歷trackSet每次選出一個離磁頭最近的磁道並輸出,把距離累加到distance中,將磁頭移到該磁道,將該磁道從trackSet中移除,直到trackSet爲空。最後輸出總路程。
System.out.print("尋道順序爲:" + headAt + " ");
while (!trackSet.isEmpty()) {
Iterator<Integer> iterator = trackSet.iterator();
int chosenOne = iterator.next();
while (iterator.hasNext()) {
int t = iterator.next();
if (Math.abs(t - this.headAt) < Math.abs(chosenOne - this.headAt))
chosenOne = t;
}
System.out.print(chosenOne + " ");
this.distance += Math.abs(this.headAt - chosenOne);
this.headAt = chosenOne;
trackSet.remove(chosenOne);
}
System.out.println();
System.out.println("總路程=" + this.distance);
}
SCAN
電梯調度算法首先將當前訪問序列進行冒泡排序,然後在排序後的數組中找到當前磁頭的序號head,根據輸入的磁頭移動方向分別移動並輸出,同時把距離累加到distance中,最後輸出總路程。
private void SCAN() {
System.out.print("尋道順序爲:" + headAt + " ");
int[] orderTracks = this.tracks.clone();
for (int i = 0; i < orderTracks.length; i++) {
for (int j = i + 1; j < orderTracks.length; j++) {
if (orderTracks[i] > orderTracks[j]) {
int t = orderTracks[i];
orderTracks[i] = orderTracks[j];
orderTracks[j] = t;
}
}
}
int head = 0;
for (int i = 0; i < orderTracks.length&&orderTracks[i]<headAt; i++) {
head++;
}
if (direction) {
for (int i = head; i < orderTracks.length; i++) {
System.out.print(orderTracks[i] + " ");
this.distance += Math.abs(this.headAt - orderTracks[i]);
this.headAt = orderTracks[i];
}
for (int i = head - 1; i >= 0; i--) {
System.out.print(orderTracks[i] + " ");
this.distance += Math.abs(this.headAt - orderTracks[i]);
this.headAt = orderTracks[i];
}
} else {
for (int i = head; i < orderTracks.length; i++) {
System.out.print(orderTracks[i] + " ");
this.distance += Math.abs(this.headAt - orderTracks[i]);
this.headAt = orderTracks[i];
}
for (int i = head - 1; i >= 0; i--) {
System.out.print(orderTracks[i] + " ");
this.distance += Math.abs(this.headAt - orderTracks[i]);
this.headAt = orderTracks[i];
}
}
System.out.println();
System.out.println("總路程=" + this.distance);
}
實驗結果
測試用例
int[] tracks = {98, 183, 37, 122, 14, 124, 65, 67};
FCFS
1.FCFS 2.SSTF 3.SCAN
請輸入調度算法:1
請輸入磁頭起始位置:
53
請輸入方向(0.左 1.右):
0
尋道順序爲:53 98 183 37 122 14 124 65 67
總路程=640Process finished with exit code 0
SSTF
1.FCFS 2.SSTF 3.SCAN
請輸入調度算法:2
請輸入磁頭起始位置:
53
請輸入方向(0.左 1.右):
0
尋道順序爲:53 65 67 37 14 98 122 124 183
總路程=236Process finished with exit code 0
SCAN
1.FCFS 2.SSTF 3.SCAN
請輸入調度算法:3
請輸入磁頭起始位置:
53
請輸入方向(0.左 1.右):
0
尋道順序爲:53 37 14 65 67 98 122 124 183
總路程=208Process finished with exit code 0
馬後炮
調試過程
調試基本沒有出現很大的問題,主要出現的是一些小細節的地方,比如數組越界等問題,經過調試後便能正常運行。
小結
磁盤調度實驗是操作系統三次實驗裏最簡單的一個,主要考察的實際是對調度思想的理解,實際代碼的難度並不大,代碼上的難點頂多就於數組的遍歷。