作業系統實驗之磁碟排程
實驗要求
- 選擇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
馬後炮
除錯過程
除錯基本沒有出現很大的問題,主要出現的是一些小細節的地方,比如陣列越界等問題,經過除錯後便能正常執行。
小結
磁碟排程實驗是作業系統三次實驗裡最簡單的一個,主要考察的實際是對排程思想的理解,實際程式碼的難度並不大,程式碼上的難點頂多就於陣列的遍歷。