canvas-demo
canvas模擬實現(xiàn)磁盤調(diào)度算法 Canvas simulation implements disk scheduling algorithm
項目地址:canvas-demo
demo
界面
實現(xiàn)過程
1.定義磁盤磁道總個數(shù)和需要生成的磁道序列個數(shù):
const track = 150;
const trackNumber = 40;
2.定義磁道序列數(shù)組
let trackSequence = [];
3.生成trackNumber個磁道號序列
generateTrackNumberSequence(trackNumber);
4.根據(jù)用戶設(shè)置的算法和磁頭初始位置形成相應(yīng)的磁頭軌跡數(shù)組
(1)先來先服務(wù)算法(FCFS)
這種算法的思想比較容易理解。假設(shè)當(dāng)前磁道在某一位置,依次處理服務(wù)隊列里的每一個磁道,這樣做的優(yōu)點是處理起來比較簡單,但缺點是磁頭移動的距離和平均移動距離會很大。
實現(xiàn)方法:依次將磁頭初始位置和磁道號序列放入磁頭軌跡數(shù)組即可。
function fcfs(headInitalPosition) {
let headPath = [];
headPath.push(headInitalPosition);
return headPath.concat(trackSequence);
}
(2)最短尋道時間算法(SSTF)
這種算法的本質(zhì)是利用貪心算法來實現(xiàn),假設(shè)當(dāng)前磁道在某一位置,接下來處理的是距離當(dāng)前磁道最近的磁道號,處理完成之后再處理離這個磁道號最近的磁道號,直到所有的磁道號都服務(wù)完了程序結(jié)束。這樣做的優(yōu)點是性能會優(yōu)于FIFO算法,但是會產(chǎn)生距離當(dāng)前磁道較遠(yuǎn)的磁道號長期得不到服務(wù),也就是“饑餓”現(xiàn)象。
實現(xiàn)方法:形成一個當(dāng)前磁頭位置與磁道號序列里每個元素距離的數(shù)組distance,在distance里找到最小值并返回下標(biāo),通過該下標(biāo)找到磁道號序列里面對應(yīng)的磁道號,并將該磁道號加入磁頭軌跡數(shù)組。一直循環(huán)上述方法。
function sstf(headInitalPosition) {
let headPath = [];
headPath.push(headInitalPosition);
let trackSequenceCopy = trackSequence.concat();
for(let i = 0; i < trackSequence.length; i++) {
let distance = trackSequenceCopy.map(key => Math.abs(key - headPath[i]));
let minCoor = distance.min();
headPath.push(trackSequenceCopy[minCoor]);
trackSequenceCopy.splice(minCoor, 1);
}
return headPath;
}
(3)電梯調(diào)度算法(SCAN)
先按照一個方向(比如從外向內(nèi)掃描),掃描的過程中依次訪問要求服務(wù)的序列。當(dāng)掃描到最里層的一個服務(wù)序列時反向掃描。
實現(xiàn)方法:將磁道序列里面小于等于初始磁頭位置的元素按降序排好后插入磁頭軌跡數(shù)組,再將磁道號序列里面大于初始磁頭位置的元素按升序排好后插入磁頭軌跡數(shù)組。
function scan(headInitalPosition) {
let headPath = [];
headPath.push(headInitalPosition);
headPath = headPath.concat((trackSequence.filter(key => key <= headInitalPosition)).sort((a, b) => b - a));
headPath = headPath.concat((trackSequence.filter(key => key > headInitalPosition)).sort((a, b) => a - b));
return headPath;
}
(4)循環(huán)掃描算法(C-SCAN)
CSCAN算法的思想是,訪問完最里面一個要求服務(wù)的序列之后,立即回到最外層欲訪問磁道。也就是始終保持一個方向。故也稱之為單向掃描調(diào)度算法。
實現(xiàn)方法:將磁道序列里面小于等于初始磁頭位置的元素按降序排好后插入磁頭軌跡數(shù)組,再將磁道號序列里面大于初始磁頭位置的元素按降序排好后插入磁頭軌跡數(shù)組。
function cScan(headInitalPosition) {
let headPath = [];
headPath.push(headInitalPosition);
headPath = headPath.concat((trackSequence.filter(key => key <= headInitalPosition)).sort((a, b) => b - a));
headPath = headPath.concat((trackSequence.filter(key => key > headInitalPosition)).sort((a, b) => b - a));
return headPath;
}
5.效果圖
(1)繪制X軸及標(biāo)記點
/**
* 繪制X軸及標(biāo)記點
*
* @param {Array} xCoorArray 按升序排好的橫坐標(biāo)數(shù)組
*/
function drawCoordinateAxis(xCoorArray) {
ctx.strokeStyle = '#566a80';
ctx.fillStyle = '#566a80';
ctx.lineWidth = 2;
for(let i = 0; i < xCoorArray.length; i++) {
const startXCoor = (xCoorArray[i] / track) * canvas.width;
const endYCoor = (xCoorArray[i + 1] / track) * canvas.width;
drawText(xCoorArray[i], startXCoor, 25);
drawLine(startXCoor, 40, endYCoor, 40);
drawLine(startXCoor, 40, startXCoor, 30);
}
}
(2)繪制折線圖
/**
* 繪制折線圖
*
* @param {Array} headPath 磁頭軌跡數(shù)組
*/
function drawLineChart(headPath) {
ctx.strokeStyle = '#566a80';
ctx.fillStyle = '#566a80';
ctx.lineWidth = 2;
ctx.lineJoin = 'round';
ctx.lineCap = 'round';
//起點和終點縱坐標(biāo)
let startYCoor = 50;
let endYCoor = 60;
for(let i = 0; i < headPath.length; i++) {
//起點和終點橫坐標(biāo)
let startXCoor = (headPath[i] / track) * canvas.width;
let endXCoor = (headPath[i + 1] / track) * canvas.width;
if(startXCoor == endXCoor) {
endYCoor = startYCoor;
}
drawPoint(startXCoor, startYCoor, 5);
drawLine(startXCoor, startYCoor, endXCoor, endYCoor);
startYCoor = endYCoor;
endYCoor += 10;
}
}
(3)顯示磁頭移動道數(shù)
將磁頭軌跡數(shù)組中各元素的差值的絕對值放如數(shù)組moveNumber中,將moveNumber中各元素依次相加。