1. 程式人生 > >作業系統課程設計--磁碟排程演算法的模擬實現及對比

作業系統課程設計--磁碟排程演算法的模擬實現及對比

本來已經做好了個課程設計是銀行家演算法的,不過由於借給同學抄,被老師發現了,要重做...就選了磁碟高度演算法的題目。

實驗要求及提示

1 、首先假設磁碟磁軌數為 1500 ,磁頭初始停止於 0 磁軌。

2 、用隨機數生成函式產生“磁軌號”序列(即磁碟請求的位置),共產生 100 個。其中 50% 位於 0 499 25% 分佈在 500 999 25% 分佈在 1000 1499

       3 、計算每種磁碟排程演算法下的磁頭移動道數

本程式主要是模擬實現,還有很多改進的地方,還請大家提出。

以下是為滿足要求2的隨機數生成程式碼,主要參照網上的方法:

package chow.app;

import java.util.HashSet;
import java.util.Iterator;
import java.util.Random;

/**
 * 用隨機數生成函式產生“磁軌號”序列(即磁碟請求的位置),共產生100個。其中50%位於0~499,25%分佈在500~999,25%分佈在1000~1499。
 * @author Administrator
 */
public class DiskScheduleUtil {

    public static int count = 0;// 需要生成隨機數的個數

    public int[] createDiskRequest() {
        int[] tmpRequest = new int[100];
        HashSet<Integer> s = new HashSet<Integer>();
        // 50%位於0~499的序列
        count = 50;
        genRadoms(0, 499, count, s);
        Iterator<Integer> it;
        it = s.iterator();
        int i = 0;
        while (it.hasNext()) {
            tmpRequest[i] = it.next();
            i++;
        }
        // 25%分佈在500~999的序列
        count = 25;
        s.clear();
        genRadoms(500, 999, count, s);
        it = s.iterator();
        i = 50;
        while (it.hasNext()) {
            tmpRequest[i] = it.next();
            i++;
        }
        //25%分佈在1000~1499的序列
        count = 25;
        s.clear();
        genRadoms(1000, 1499, count, s);
        it = s.iterator();
        i = 75;
        while (it.hasNext()) {
            tmpRequest[i] = it.next();
            i++;
        }
        //用來打亂tmpRequest的順序
        int[] tmpRequestReturn = new int[100];
        int[] nosortSeq = random2();
        for(int j = 0; j  < 100; j++){
            tmpRequestReturn[j] = tmpRequest[nosortSeq[j]];
            System.out.print("[" + j + "]:" + tmpRequestReturn[j] + " ");
            if (j % 10 == 0) {
                System.out.println();
            }
        }
        return tmpRequestReturn;
    }

    // 生成【begin,end】區間內num個隨機數
    public void genRadoms(int begin, int end, int num, HashSet<Integer> set) {
        if (num > (end - begin + 1) || end < begin) {
            return;
        }
        for (int i = 0; i < num; i++) {// 生成num個隨機數
            // 呼叫Math.random()方法
            int temp = (int) (Math.random() * (end - begin + 1)) + begin;
            set.add(temp);// 將不同的數存入HashSet中
        }
        int setLen = set.size();
        // 如果存入的數小於指定生成的個數,則呼叫遞迴再生成剩餘個數的隨機數,如此迴圈,直到達到指定大小
        if (setLen < count) {
            genRadoms(begin, end, count - setLen, set);// 遞迴
        }
    }


    public static int[] random2() {
        int send[] = new int[100];
        for(int i = 0; i < send.length; i++){
            send[i] = i;
        }
        int temp1, temp2, temp3;
        Random r = new Random();
        for (int i = 0; i < send.length; i++) // 隨機交換send.length次
        {
            temp1 = Math.abs(r.nextInt()) % (send.length - 1); // 隨機產生一個位置
            temp2 = Math.abs(r.nextInt()) % (send.length - 1); // 隨機產生另一個位置
            if (temp1 != temp2) {
                temp3 = send[temp1];
                send[temp1] = send[temp2];
                send[temp2] = temp3;
            }
        }
        return send;
    }

}

以下是FCFS,SSTF,SCAN,C-SCAN各演算法的程式碼,每個演算法都返回磁碟移動的磁軌數。

FCFS演算法,first come first service.

package chow.app;

/**
 * first come, first service
 * @author Administrator
 */
public class DiskScheduleFCFS extends DiskScheduleAlgorithm{
    @Override
    public int getCount(final int[] diskReq, int varIndex){
        count = 0;
        curIndex = varIndex;
        for(int i = 0; i < diskReq.length; i++){
            count += Math.abs(diskReq[i] - curIndex);
            curIndex = diskReq[i];
        }
        return count;
    }

}

SSTF演算法,shortest seek time first

package chow.app;

/**
 * shortest seek time first 最短尋道時間優先演算法
 * @author Administrator
 */
public class DiskScheduleSSTF extends DiskScheduleAlgorithm {

    @Override
    public int getCount(final int[] diskReq, int varIndex) {
        count = 0;
        curIndex = varIndex;
        int[] tmpDiskReq = new int[diskReq.length];
        for(int tInt = 0; tInt < diskReq.length; tInt++){
            tmpDiskReq[tInt] = diskReq[tInt];
        }
        for (int i = 0; i < tmpDiskReq.length; i++) {
            int index = getNearestIndex(curIndex,tmpDiskReq);
            count += Math.abs(curIndex - tmpDiskReq[index]);
            System.out.print(tmpDiskReq[index]+" ");
            if(i%10==0)
                System.out.println();
            curIndex = tmpDiskReq[index];
            tmpDiskReq[index] = -1;
        }
        return count;
    }

    //返回距離當前最近的索引
    public int getNearestIndex(int tmpIndex,final int[] tdiskReq) {
        int min = 1500;
        int temp = 0;
        int index = -1;
        for (int i = 0; i < tdiskReq.length; i++) {
            if (tdiskReq[i] != -1) {
                temp = Math.abs(tmpIndex - tdiskReq[i]);
                if (temp < min) {
                    min = temp;
                    index = i;
                }
            }
        }
        return index;
    }
}

SCAN演算法,又叫做“電梯演算法”,我是處理完最遠一個請求就返回另一方向繼續處理。也有教材上是一直移動到末端才轉方向的。

/**
 * SCAN 電梯演算法,先不斷移到一端(盡頭),再移到另一端(另一盡頭)
 * 簡化:預設為先大數端後向0端;不移到末端,只移到最外一個請求就轉向
 * @author Administrator
 */
public class DiskScheduleSCAN extends DiskScheduleAlgorithm{
    @Override
    public int getCount(final int[] diskReq, int varIndex) {
        count = 0;
        curIndex = varIndex;
        int leftMin = curIndex, rightMax = curIndex;
        for(int i = 0; i < diskReq.length; i++){
            if(diskReq[i] > curIndex && diskReq[i] > rightMax){
                rightMax = diskReq[i];
            }else if(diskReq[i] < curIndex && diskReq[i] < leftMin){  // 小於等於curIndex
                leftMin = diskReq[i];
            }
        }
        if(curIndex==leftMin){
            count = rightMax - curIndex;
        }else{
            count = (rightMax - curIndex) + (rightMax - leftMin);
        }
        return count;
    }
    
}
 

C-SCAN演算法,SCAN演算法的變種

package chow.app;

/**
 * C-SCAN, 是SCAN的變種,當碰頭移到另一端時,馬上返回到磁碟開始,返回時不處理請求
 * @author Administrator
 */
public class DiskScheduleC_SCAN extends DiskScheduleAlgorithm{
    @Override
    public int getCount(final int[] diskReq, int varIndex) {
        count = 0;
        curIndex = varIndex;
        int leftMax = lowIndex, rightMax = curIndex;
        for(int i = 0; i < diskReq.length; i++){
            if(diskReq[i] > curIndex && diskReq[i] > rightMax){
                rightMax = diskReq[i];
            }else if(diskReq[i] < curIndex && diskReq[i] > leftMax){  // 小於curIndex
                leftMax = diskReq[i];
            }
        }
        if(curIndex==leftMax){
            count = rightMax - curIndex;
        }else{
            count = (rightMax - curIndex) + (highIndex - lowIndex) + leftMax;
        }
        return count;
    }
}
 

以上是關鍵程式碼,其它的介面是在netbeans6.7上完成的。下面上傳最終生成的jar檔案。