作業系統-磁碟排程演算法
阿新 • • 發佈:2018-12-26
實驗七 磁碟排程演算法
磁碟排程在多道程式設計的計算機系統中,各個程序可能會不斷提出不同的對磁碟進行讀/寫操作的請求。由於有時候這些程序的傳送請求的速度比磁碟響應的還要快,因此我們有必要為每個磁碟裝置建立一個等待佇列,常用的磁碟排程演算法有以下四種:
先來先服務演算法(FCFS ),
最短尋道時間優先演算法(SSTF ),
掃描演算法(SCAN ),
迴圈掃描演算法(CSCAN )
這是一種比較簡單的磁碟排程演算法。它根據程序請求訪問磁碟的先後次序進行排程。此演算法的優點是公平、簡單,且每個程序的請求都能依次得到處理,不會出現某一程序的請求長期得不到滿足的情況。此演算法由於未對尋道進行優化,在對磁碟的訪問請求比較多的情況下,此演算法將降低裝置服務的吞吐量,致使平均尋道時間可能較長,但各程序得到服務的響應時間的變化幅度較小。
先來先服務 (125)86.147.91.177.94.150.102.175.130
2 、最短尋道時間優先演算法(SSTF ) Shortest Seek Time First
該演算法選擇這樣的程序,其要求訪問的磁軌與當前磁頭所在的磁軌距離最近,以使每次的尋道時間最短,該演算法可以得到比較好的吞吐量,但卻不能保證平均尋道時間最短。其缺點是對使用者的服務請求的響應機會不是均等的,因而導致響應時間的變化幅度很大。在服務請求很多的情況下,對內外邊緣磁軌的請求將會無限期的被延遲,有些請求的響應時間將不可預期。
最短尋道時間優先(125)130.147.150.175.177.102.94.91.86
3 、掃描演算法(SCAN )電梯排程
掃描演算法不僅考慮到欲訪問的磁軌與當前磁軌的距離,更優先考慮的是磁頭的當前移動方向。例如,當磁頭正在自裡向外移動時,掃描演算法所選擇的下一個訪問物件應是其欲訪問的磁軌既在當前磁軌之外,又是距離最近的。這樣自裡向外地訪問,直到再無更外的磁軌需要訪問才將磁臂換向,自外向裡移動。這時,同樣也是每次選擇這樣的程序來排程,即其要訪問的磁軌,在當前磁軌之內,從而避免了飢餓現象的出現。由於這種演算法中磁頭移動的規律頗似電梯的執行,故又稱為電梯排程演算法。此演算法基本上克服了最短尋道時間優先演算法的服務集中於中間磁軌和響應時間變化比較大的缺點,而具有最短尋道時間優先演算法的優點即吞吐量較大,平均響應時間較小,但由於是擺動式的掃描方法,兩側磁軌被訪問的頻率仍低於中間磁軌。
電梯排程(125)102.94.91.86.130.147.150.175.177
4 、迴圈掃描演算法(CSCAN )
迴圈掃描演算法是對掃描演算法的改進。如果對磁軌的訪問請求是均勻分佈的,當磁頭到達磁碟的一端,並反向運動時落在磁頭之後的訪問請求相對較少。這是由於這些磁軌剛被處理,而磁碟另一端的請求密度相當高,且這些訪問請求等待的時間較長,為了解決這種情況,迴圈掃描演算法規定磁頭單向移動。例如,只自裡向外移動,當磁頭移到最外的被訪問磁軌時,磁頭立即返回到最裡的欲訪磁軌,即將最小磁軌號緊接著最大磁軌號構成迴圈,進行掃描。
迴圈掃描 (125)130.147.150.175.177.86.91.94.102
5 、平均尋道距離
假設當前磁頭在 67 號,要求訪問的磁軌號順序為 98,25,63,97,56,51,55,55,6
FIFO 演算法的服務序列是:98,25,63,97,56,51,55,55,6
磁頭移動的總距離 distance =
(98-67)+(98-25)+(63-25)+(97-63)+(97-56)+(56-51)+(55-51)+(55-55)+(55-6)
SSTF 演算法的服務序列是: 63,56,55,55,51,25,6,97,98
磁頭移動的總距離 distance =
(67-63)+(63-56)+(56-55)+(55-55)+(55-51)+(51-25)+(25-6)+(97-6)+(98-97)
SCAN 演算法的服務序列是:63,56,55,55,51,25,6,97,98
磁頭移動的總距離 distance =
(67-63)+(63-56)+(56-55)+(55-55)+(55-51)+(51-25)+(25-6)+(97-6)+(98-97)
我發現這裡例子舉的不好,SSTF 和 SCAN 演算法的服務序列竟是一樣的,尷
尬!
CSCAN 演算法的服務序列是:63,56,55,55,51,25,6,98,97
磁頭移動的總距離 distance =
(67-63)+(63-56)+(56-55)+(55-55)+(55-51)+(51-25)+(25-6)+(100-98)+(98-97)
先來先服務演算法(FCFS ),
最短尋道時間優先演算法(SSTF ),
掃描演算法(SCAN ),
迴圈掃描演算法(CSCAN )
例: 假定某磁碟共有200個柱面,編號為 0-199,如果在為訪問 143 號柱面的請求者服務後,當前正在為訪問 125 號柱面的請求服務,同時有若干請求者在等待服務,它們每次要訪問的柱面號為 86 ,147 ,91 ,177 ,94 ,150 ,102, 175 ,130
1 、先來先服務演算法(FCFS )First Come First Service這是一種比較簡單的磁碟排程演算法。它根據程序請求訪問磁碟的先後次序進行排程。此演算法的優點是公平、簡單,且每個程序的請求都能依次得到處理,不會出現某一程序的請求長期得不到滿足的情況。此演算法由於未對尋道進行優化,在對磁碟的訪問請求比較多的情況下,此演算法將降低裝置服務的吞吐量,致使平均尋道時間可能較長,但各程序得到服務的響應時間的變化幅度較小。
先來先服務 (125)86.147.91.177.94.150.102.175.130
2 、最短尋道時間優先演算法(SSTF ) Shortest Seek Time First
該演算法選擇這樣的程序,其要求訪問的磁軌與當前磁頭所在的磁軌距離最近,以使每次的尋道時間最短,該演算法可以得到比較好的吞吐量,但卻不能保證平均尋道時間最短。其缺點是對使用者的服務請求的響應機會不是均等的,因而導致響應時間的變化幅度很大。在服務請求很多的情況下,對內外邊緣磁軌的請求將會無限期的被延遲,有些請求的響應時間將不可預期。
最短尋道時間優先(125)130.147.150.175.177.102.94.91.86
3 、掃描演算法(SCAN )電梯排程
掃描演算法不僅考慮到欲訪問的磁軌與當前磁軌的距離,更優先考慮的是磁頭的當前移動方向。例如,當磁頭正在自裡向外移動時,掃描演算法所選擇的下一個訪問物件應是其欲訪問的磁軌既在當前磁軌之外,又是距離最近的。這樣自裡向外地訪問,直到再無更外的磁軌需要訪問才將磁臂換向,自外向裡移動。這時,同樣也是每次選擇這樣的程序來排程,即其要訪問的磁軌,在當前磁軌之內,從而避免了飢餓現象的出現。由於這種演算法中磁頭移動的規律頗似電梯的執行,故又稱為電梯排程演算法。此演算法基本上克服了最短尋道時間優先演算法的服務集中於中間磁軌和響應時間變化比較大的缺點,而具有最短尋道時間優先演算法的優點即吞吐量較大,平均響應時間較小,但由於是擺動式的掃描方法,兩側磁軌被訪問的頻率仍低於中間磁軌。
電梯排程(125)102.94.91.86.130.147.150.175.177
4 、迴圈掃描演算法(CSCAN )
迴圈掃描演算法是對掃描演算法的改進。如果對磁軌的訪問請求是均勻分佈的,當磁頭到達磁碟的一端,並反向運動時落在磁頭之後的訪問請求相對較少。這是由於這些磁軌剛被處理,而磁碟另一端的請求密度相當高,且這些訪問請求等待的時間較長,為了解決這種情況,迴圈掃描演算法規定磁頭單向移動。例如,只自裡向外移動,當磁頭移到最外的被訪問磁軌時,磁頭立即返回到最裡的欲訪磁軌,即將最小磁軌號緊接著最大磁軌號構成迴圈,進行掃描。
迴圈掃描 (125)130.147.150.175.177.86.91.94.102
5 、平均尋道距離
假設當前磁頭在 67 號,要求訪問的磁軌號順序為 98,25,63,97,56,51,55,55,6
FIFO 演算法的服務序列是:98,25,63,97,56,51,55,55,6
磁頭移動的總距離 distance =
(98-67)+(98-25)+(63-25)+(97-63)+(97-56)+(56-51)+(55-51)+(55-55)+(55-6)
SSTF 演算法的服務序列是: 63,56,55,55,51,25,6,97,98
磁頭移動的總距離 distance =
(67-63)+(63-56)+(56-55)+(55-55)+(55-51)+(51-25)+(25-6)+(97-6)+(98-97)
SCAN 演算法的服務序列是:63,56,55,55,51,25,6,97,98
磁頭移動的總距離 distance =
(67-63)+(63-56)+(56-55)+(55-55)+(55-51)+(51-25)+(25-6)+(97-6)+(98-97)
我發現這裡例子舉的不好,SSTF 和 SCAN 演算法的服務序列竟是一樣的,尷
尬!
CSCAN 演算法的服務序列是:63,56,55,55,51,25,6,98,97
磁頭移動的總距離 distance =
(67-63)+(63-56)+(56-55)+(55-55)+(55-51)+(51-25)+(25-6)+(100-98)+(98-97)
6、參考程式碼
#include <iostream> #include <vector> #include <fstream> using namespace std; typedef vector<int> vInt; //向量,動態陣列 struct OrderItem { int Data; bool IsVisited; }; typedef vector<OrderItem> Order; Order InitOrder; vInt TrackOrder; vInt MoveDistance; double AverageDistance; void InitDate(int &num); inline void Init(int disk); //行內函數(行內函數的程式碼會在任何呼叫它的地方展開) void FCFS(int disk); void SSTF(int disk); void SCAN(int disk); void CSCAN(int disk); void Show(int disk); int main() { int num; InitDate(num); char cmd; do { cout<<"選擇演算法:\n"<<"1-FCFS,2-SSTF,3-SCAN,4-CSCAN:\t"; int type;cin>>type; switch(type) { case 1:FCFS(num);break; case 2:SSTF(num);break; case 3:SCAN(num);break; case 4:CSCAN(num);break; } Show(num); cout<<"Continue? y or n?\t"; cin>>cmd; }while(cmd!='n'); return 0; } inline void Init(int disk) { TrackOrder.clear(); MoveDistance.clear(); for(int i = 0; i < disk; i++) { InitOrder[i].IsVisited = false; } } void InitDate(int &num) { //ifstream cin("data.txt"); cout<<"輸入磁軌個數"; cin>>num; cout<<"磁碟訪問序列"; for(int i=0; i<num; i++) { OrderItem oi; cin>>oi.Data; oi.IsVisited = false; InitOrder.push_back(oi); } } void FCFS(int disk) { cout<<"輸入開始磁碟號"; int start;cin>>start; cout<<"FCFS:"<<endl; int p = start; Init(disk); for(int i = 0 ; i < disk; i++ ) { TrackOrder.push_back(InitOrder[i].Data); int t = InitOrder[i].Data-p; MoveDistance.push_back(t>0?t:-t); InitOrder[i].IsVisited = true; p = InitOrder[i].Data; } } void SSTF(int disk) { cout<<"輸入開始磁碟號"; int start;cin>>start; cout<<"SSTF:"<<endl; Init(disk); int curp=0,dif=0; int p = start; for(int i = 0; i < disk; i++) { int temp = 0; for(int j = 0 ; j < disk; j++) { if(InitOrder[j].IsVisited == false) { temp = p-InitOrder[j].Data>0? p-InitOrder[j].Data:-(p-InitOrder[j].Data); if(dif==0||temp<dif) { dif = temp; curp = j; } } } InitOrder[curp].IsVisited = true; TrackOrder.push_back(InitOrder[curp].Data); MoveDistance.push_back(dif); p = InitOrder[curp].Data; dif = 0; } } void SCAN(int disk) { cout<<"輸入開始磁碟號"; int start;cin>>start; cout<<"選擇訪問方向:0-磁軌號遞增1-磁軌號遞減\t"; int dir; cin>>dir; cout<<"SSTF:"<<endl; Init(disk); int curp=0,dif=0,cdir=dir,max=InitOrder[0].Data,min=max; for(int i =1; i<disk;i++) { if(max<InitOrder[i].Data) max = InitOrder[i].Data; if(min>InitOrder[i].Data) min = InitOrder[i].Data; } int p = start; for(int k = 0; k< disk; k++) { int temp = 0; for(int j = 0 ; j < disk; j++) { if(cdir==0&&p>InitOrder[j].Data||cdir==1&&p<InitOrder[j].Data) continue; if(InitOrder[j].IsVisited == false) { temp = p-InitOrder[j].Data>0? p-InitOrder[j].Data:-(p-InitOrder[j].Data); if(dif==0||temp<dif) { dif = temp; curp = j; } } } if(dir==0&&InitOrder[curp].Data==max)cdir = 1; if(dir==1&&InitOrder[curp].Data==min)cdir = 0; InitOrder[curp].IsVisited = true; TrackOrder.push_back(InitOrder[curp].Data); MoveDistance.push_back(dif); p = InitOrder[curp].Data; dif = 0; } } void CSCAN(int disk) { cout<<"輸入開始磁碟號"; int start;cin>>start; cout<<"選擇訪問方向:0-磁軌號遞增1-磁軌號遞減\t"; int dir; cin>>dir; cout<<"CSSTF:"<<endl; Init(disk); int curp=0,dif=-1,max=InitOrder[0].Data,min=max,mmin=0,mmax=0; for(int i =1; i<disk;i++)//找到磁軌序列中最小和最大的磁軌號及下標 { if(max<InitOrder[i].Data) { max = InitOrder[i].Data; mmax = i; } if(min>InitOrder[i].Data) { min = InitOrder[i].Data; mmin=i; } } int p = start;//p表示上一個訪問的磁軌號 for(int k = 0; k < disk; k++) { int temp = 0; for(int j = 0 ; j < disk; j++)//查詢下一個要訪問的磁軌 { if(dir==0&&p>InitOrder[j].Data||dir==1&&p<InitOrder[j].Data) continue; if(InitOrder[j].IsVisited == false)//dir方向且未被訪問的項 { temp = p-InitOrder[j].Data>0? (p-InitOrder[j].Data):(InitOrder[j].Data-p); if(dif==-1||temp<dif) { dif = temp; curp = j;//找到下一個被訪問的磁軌 } } } InitOrder[curp].IsVisited = true;//訪問 TrackOrder.push_back(InitOrder[curp].Data); MoveDistance.push_back(dif); p = InitOrder[curp].Data; //達到極限點 if(dir==0&&InitOrder[curp].Data==max&&InitOrder[mmin].IsVisited==false) { //從最小項開始 TrackOrder.push_back(min); InitOrder[mmin].IsVisited = true; MoveDistance.push_back(p-TrackOrder[mmin]>=0? p-TrackOrder[mmin]:TrackOrder[mmin]-p); curp = mmin; } if(dir==1&&InitOrder[curp].Data==min&&InitOrder[mmax].IsVisited==false) { TrackOrder.push_back(max); InitOrder[mmax].IsVisited = true; MoveDistance.push_back(p-TrackOrder[mmin]>=0? p-TrackOrder[mmin]:TrackOrder[mmin]-p); curp = mmax; } p = InitOrder[curp].Data; dif = -1; } } void Show(int disk) { cout<<"被訪問的下一個磁軌號\t"<<"移動距離"<<endl; int sum=0; for(int i = 0 ; i <disk; i++) { sum+=MoveDistance[i]; cout<<"\t"<<TrackOrder[i]<<"\t\t "<<MoveDistance[i]<<endl; } AverageDistance = (double)sum/disk; cout<<"平均尋道長度:"<<AverageDistance<<endl; }