《操作系統》——硬盤掃描問題的算法實現

《操作系統》課程實驗(五)

——生產者消費者同步問題的算法實現

磁盤是可供多個進程共享的設備,當有多個進程都要求訪問磁盤是,應採用一種最佳調度算法,以使各進程對磁盤的平均訪問時間最小。目前最成用的磁盤調度算法有先來先服務(FCFS),最短尋道時間優先(SSTF),以及掃描算法(SCAN)。通過本實驗可以加深理解有關磁盤調度的目標,並體會和了解最短尋道時間優先算法和掃描算法的具體實施辦法。

  1. 從100#磁道開始,被訪問的磁道號分別爲:55,58,39,18,90,160,150,38,184。
  2. 要求用最短尋道時間優先算法的和掃描算法實現磁盤調度。
  3. 記錄下每訪問一個磁道磁頭移動的磁道數,並計算平均尋道長度(平均移動磁道數)。

 

編程語言:Java

開發工具:IntelliJ IDEA

 

  1. 實驗要求

 

分別用兩種算法實現磁盤調度。在實驗結果分析中,將比較結果以列表的形式表現出來。用數組(或鏈表)TR[ ]存儲待訪問磁道號,將每次磁頭移動磁道數用數組AR[ ] 存儲。輸出結果應如下例:(注意空格)

 

 

 

150

50

160

10

,184

24

18,,

166

38

20

39

1

55

16

58

3

90

32

平均尋道長度:35.8

 

  1. 實驗代碼
  1. 類名:Request //請求
public class Request {
    private int id;//請求號,唯一標識一個請求
    private int number;//欲訪問的磁道號
    private int flag;//是否已被調度的標記,初始爲0,表示爲被調度。
    public Request(){//空白構造器
        this.id=0;
        this.number=0;
        this.flag=0;
    }
    public Request(int id,int num){//帶參構造器
        this.id=id;
        this.number=num;
        this.flag=0;
    }
    public void setId(int id){
        this.id=id;
    }
    //以下是一系列set和get方法
    public int getId(){
        return this.id;
    }
    public void setNumber(int number){
        this.number=number;
    }
    public int getNumber(){
        return this.number;
    }
    public void setFlag(int flag){
        this.flag=flag;
    }
    public int getFlag(){
        return this.flag;
    }
}

 

  1. 類名:Diaodu //最短尋道
public class DiaoDu {
    Work work;
    Request[] request;
    int begin;//磁頭初始位置
    DecimalFormat df = new DecimalFormat("0.000");
    public DiaoDu(Work work){//構造器,接收一個作業
        this.work=work;
        request=work.getRandomRequest();
        //磁頭初始位置設爲所允許訪問磁道號範圍的中間值。
        //如若磁道訪問允許範圍爲100~300,則磁頭初始位置在200處。
        begin=(work.getStart()+work.getEnd())/2;
    }



    public void SSTF(){//最短尋道優先
        begin=(work.getStart()+work.getEnd())/2;
        Request[] req=request;
        System.out.println("磁道號區間:"+work.getStart()+"到"+work.getEnd());
        System.out.println("磁頭初始時所在磁道號:"+begin);

        int t=0;
        double sum=0;
        System.out.println("請求號        被訪問的下一個磁道號               移動距離");
        for(int i=0;i<req.length;i++){
            int temp=work.getEnd();
            for(int j=0;j<req.length;j++){
                if(Math.abs(req[j].getNumber()-begin)<temp&&req[j].getFlag()==0){
                    temp=Math.abs(req[j].getNumber()-begin);
                    t=j;
                }
            }
            System.out.println("--"+req[t].getId()+"----------------"+req[t].getNumber()+"-----------------"+temp+"--");
            begin=req[t].getNumber();
            req[t].setFlag(1);
            sum+=temp;
        }
        System.out.println("***********平均尋道長度爲:"+df.format(sum/req.length)+"***********");
    }



    public void SCAN(){//掃描算法
        begin=(work.getStart()+work.getEnd())/2;
        Request[] req=request;
        int direction;//磁頭運動方向方向
        System.out.println("設定磁頭初始化運動方向(1:磁道號增大方向    -1:磁道號減小方向):");
        direction=new Scanner(System.in).nextInt();
        System.out.println("磁道號區間:"+work.getStart()+"到"+work.getEnd());
        System.out.println("磁頭初始時所在磁道號:"+begin);
        if(direction==1)
            System.out.println("磁頭初始運動方向: 磁道號增大方向");
        else
            System.out.println("磁頭初始運動方向: 磁道號減小方向");

        Map<Integer,Request> map=new HashMap<Integer,Request>();
        TreeSet<Integer> ts1=new TreeSet<Integer>();
        TreeSet<Integer> ts2=new TreeSet<Integer>();
        for(Request r:req){
            if(r.getNumber()>=begin){
                map.put(r.getNumber(), r);
                ts1.add(r.getNumber());
            }
            else{
                map.put(r.getNumber(), r);
                ts2.add(r.getNumber());
            }
        }


        System.out.println("請求號被訪問的下一個磁道號移動距離");
        double sum=0;
        if(direction==1){

            for(int temp:ts1){
                System.out.println("--"+map.get(temp).getId()+"----------------"+temp+"-----------------"+Math.abs(temp-begin));
                sum+=Math.abs(temp-begin);
                begin=temp;
            }
            for(int temp:ts2.descendingSet()){
                System.out.println("--"+map.get(temp).getId()+"----------------"+temp+"-----------------"+Math.abs(temp-begin));
                sum+=Math.abs(temp-begin);
                begin=temp;
            }

        }

        else{
            for(int temp:ts2.descendingSet()){
                System.out.println("--"+map.get(temp).getId()+"----------------"+temp+"-----------------"+Math.abs(temp-begin));
                sum+=Math.abs(temp-begin);
                begin=temp;
            }
            for(int temp:ts1){
                System.out.println("--"+map.get(temp).getId()+"----------------"+temp+"-----------------"+Math.abs(temp-begin));
                sum+=Math.abs(temp-begin);
                begin=temp;
            }
        }
        System.out.println("***********平均尋道長度爲:"+df.format(sum/req.length)+"***********");
    }
}

 

  1. Work //掃描
public class Work {
    private int start;//允許訪問的磁道號範圍的起始磁道號
    private int end;//允許訪問的磁道號範圍的終止磁道號
    //即請求可請求訪問的磁道號在start與end之間
    private int num;//所要產生的磁盤訪問請求數量
    public Work(){//不帶參構造器
        this.start=0;
        this.end=0;
        this.num=0;
    }
    public Work(int start,int end,int num){//帶參構造器
        this.start=start;
        this.end=end;
        this.num=num;
    }
    public int getStart(){
        return this.start;
    }
    public int getEnd(){
        return this.end;
    }

    public Request[] getRandomRequest() {//產生磁盤訪問請求的方法
        Request req[] = new Request[num];//數組聲明num個請求
        Random random = new Random();
        Set<Integer> set = new HashSet<Integer>();
        while (true) {//爲num個請求依次生成要訪問的磁道號,放入set集合
            set.add((int) (random.nextInt(end - start) + start));
            if (set.size() == num)
                break;
        }
        int i = 0;
        //將set集合中的數取出依次付給各請求。使用set的目的是讓num個訪問請求要訪問的磁道號各不同。
        for (int temp : set) {
            req[i] = new Request(i + 1, temp);
            i++;
        }
        return req;
    }
}

  1. 類名:Main //主類
public class Main {
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        int start,end,num;
        Scanner in=new Scanner(System.in);
        System.out.println("設定磁道起止道號:");
        System.out.print("起始道號:");
        start=in.nextInt();
        System.out.print("終止道號:");
        end=in.nextInt();
        System.out.print("輸入磁盤訪問的請求數:");
        num=in.nextInt();

        Work work=new Work(start,end,num);
        DiaoDu diaodu=new DiaoDu(work);

        System.out.println();
        System.out.println("***********最短尋道時間優先調度法************");
        diaodu.SSTF();

        System.out.println();
        System.out.println("****************掃描調度法*****************");
        diaodu.SCAN();
    }

}

 

  1. 實驗截圖

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章