1. 程式人生 > >磁盤調度算法FCFS、SSTF、SCAN、CSCAN詳解

磁盤調度算法FCFS、SSTF、SCAN、CSCAN詳解

磁盤調度算法 Java實現

常見的磁盤調度算法有:

1.FCFS:先來先服務算法;

2.SSTF:最短尋道時間算法;

3.SCAN:掃描算法(也叫電梯調度算法);

4.CSCAN:循環掃描算法

算法的詳細介紹:

  • FCFS:算法思想非常簡單,就是不論初始磁頭在什麽位置,都是按照服務隊列的先後順序依次處理進程,可以類比隊列的先進先出。優點是進程處理起來非常簡單,但缺點顯而易見,就是平均尋道長度會很長。

Java實現:

public class fcfs {
    Scanner x=new Scanner(System.in);
    public int[] position;
    public int num;
    public fcfs()
    {
        System.out.println("Enter the number of process:");
        num=x.nextInt();
        position=new int[num];
    }
    public void input()
    {
        int i=0;
        for(i=0;i<num;i++)
            position[i]=x.nextInt();
    }
    public void algo()
    {
        int i=1;
        for(i=1;i<=num;i++)
            System.out.println("Process Accessed "+i+" at "+position[i-1]);
    }
}
  • SSTF:最短尋道時間算法,算法本質是貪心,已知磁頭的初始位置,則最先被處理就是距離磁頭位置最近的進程,處理完成後再處理距離當前磁道最近的進程,直到所有的進程被處理。該算法的優點是平均尋道長度會大大減少,缺點是距離初始磁頭較遠的服務長期得不到處理,產生“饑餓”現象。具體的思路是:通過循環尋找與初始磁頭最近的進程,將進程處理,然後將該進程標記為-1,將初始磁頭移動到該進程所在的磁道。然後依次類推,標記為-1的進程不再參與,知道所有的進程都被標記為-1,磁盤調度完成。

Java實現

public class sstfAlg{
    int num;
    int[][] position;
    int size;
    int initPos;
    int[] sequenceOfProcess ;//存儲訪問序列
    int[] sequenceOfNumber;
    Scanner sc = new Scanner(System.in);
    public sstfAlg(int a,int b,int c){
        //a means the amount of process
        //b means the inital of position
        //c means the size of disk
        num = a;
        position = new int[a][2];
        sequenceOfProcess = new int[a];
        sequenceOfNumber = new int[a];
        initPos = b;
        size = c;
    }
    public void input(){
        System.out.println("input the number of process:");
        for(int i=0;i<num;i++){
            position[i][0] = sc.nextInt();
            position[i][1] = i+1;
        }
    }
    public void myAlg(){
        int nearest = 10000;
        int index = 0 ;
        int initPos1 = initPos;
        //復制一個數組用來尋找訪問序列
        int[][] position1 = new int[num][2];
        for(int i=0 ;i<num;i++){
            position1[i][0] = position[i][0];
            position1[i][1] = i+1;
        }
        //尋找磁頭訪問的序列        
        for(int i=0;i<num;i++){
            for(int j=0;j<num;j++){
                if(position1[j][0]!=-1){
                    if(Math.abs(initPos1 - nearest)>Math.abs(position1[j][0]-initPos1)){
                        nearest = position1[j][0];
                        index = j;
                    }    
                }
            }
            sequenceOfProcess[i] = nearest;
            sequenceOfNumber[i] = index+1;
            position1[index][0] = -1;//-1表示此位置的進程已經放在了訪問序列,不在進行查詢
            initPos1 = nearest;
            nearest = 10000;        
        }
        
        for(int i=0;i<num;i++){
            System.out.println("進程"+sequenceOfNumber[i]+"在磁道"+sequenceOfProcess[i]+"完成");
        }
    }
  • SCAN:磁頭僅沿一個方向進行掃描,在掃描途中完成所有沒有完成的請求,直到磁頭到達磁盤在這個方向上的最後一個磁道或者這個方向上最後一個請求所在的磁道。利用數組存儲進程和磁道編號,依據給定的初始磁頭,先找到初始磁頭在哪兩個進程之間,然後向內掃描。當磁頭掃描到磁盤最內層即磁道0且進程還沒有全部被處理,磁頭開始向外掃描,直到所有的進程都完成。

Java實現

class scanAlgo{
    Scanner sc = new Scanner(System.in);
    int num;   //進程數量
    int[] position1; 
    int initPos;  //磁頭初始位置
    public scanAlgo(){
        System.out.println("input the amount of process:");
        num = sc.nextInt();
        position1 = new int[num+1];
        System.out.println("input the initial position:");
        initPos = sc.nextInt();
        
    }
    public void input(){
        System.out.println("input the number of process:");
        for(int i=0;i<num;i++){
            position1[i] = sc.nextInt(); //記錄進程所在的磁道號
        }
    }
    public void adjust(){
        //按照磁道編號將進程排序,就是一個冒泡排序
        for(int i=0;i<num;i++){
            for(int j=1;j<num-i;j++){
                if(position1[j-1] > position1[j]){
                    int temp = position1[j];
                    position1[j] = position1[j-1];
                    position1[j-1] = temp;
                }
            }
        }       
    }
     public void algo(){
         //尋找磁頭初始位置在哪兩個進程之間
         input();
         adjust();
         int init;  
        for(init=0;init<num-1;init++){
             if(position1[init] <= initPos && position1[init+1] > initPos)
                 break;
             //此時得到的init值就是磁頭初始位置
         }
         int start  = init;
         //磁頭先向裏掃描
         for(int i=start;i>=0;i--){
             System.out.println("The First Time Scan:"+"Process"+position[i][1]+"At Position"+position[i][0]+"Completed");
             }
         }
         //磁頭開始從初始位置向外掃描
         if(position1[init+1]!=0){
             System.out.println("This Is the Track 0");
             }
             for(int i=start+1;i<num;i++){
                System.out.println("The Second Time Scan:"+"Process"+position[i][1]+"At Position"+position[i][0]+"Completed");
             }
         }
     }  
}
  • CSCAN:在磁盤掃描算法的基礎上改變磁頭的掃描路徑:掃描到最內層之後從最外層向內繼續掃描,即掃描方向一致。該算法的思路與掃描算法基本一致,也使用二維數組進行進程編號和進程所在磁道號的存儲,算法的不同之處在於當磁頭掃描到磁盤的最內層時,磁頭跳轉到磁盤最外層重新向內掃描,這樣就可以有效的避免將已經掃描過的磁道重新掃描一次,降低了平均尋到距離。

Java實現

class cscanAlg{
    Scanner sc = new Scanner(System.in);
    int num;
    int[][] position ;
    int initPos;
    int size;
    public cscanAlg (){
        System.out.println("input the amount of process:");
        num = sc.nextInt();
        position = new int[num+1][2];
        System.out.println("input the initial position :");
        initPos = sc.nextInt();    
        System.out.println("input the size of Disk:");
        size = sc.nextInt();
    }
    public void input(){
        System.out.println("input the number of process:");
        for(int i = 0;i<num;i++ ){
            position[i][0] = sc.nextInt();
            position[i][1] = i+1;
        }
    }
    public void adjust(){//調整數組中進程的記錄順序
        for(int i=0;i<num;i++){
            for(int j=1;j<num-i;j++){
                if(position[j-1][0]>position[j][0]){
                    int temp1 = position[j][0];
                    int temp2 = position[j][1];
                    
                    position[j][0] = position[j-1][0];
                    position[j][1] = position[j-1][1];
                    
                    position[j-1][0] = temp1;
                    position[j-1][1] = temp2;
                }
            }
        }
    }
     public void algo(){
         input();
         adjust();
         int init;
         
         for(init = 0;init<num-1;init++){
             if(position[init][0]<initPos && position[init+1][0]>=initPos){
                 break;
             }
         }
         int start = init;
         System.out.println("第一次掃描:");
         for(int i=start;i>=0;i--){       
             System.out.println("第一次掃描:"+"進程"+position[i][1]+"在磁道"+position[i][0]+"完成");     
         }
         
         if(position[init+1][0]!=0){
             System.out.println("磁頭已經掃描到磁盤最內層:0");             
         }
         if(position[num-1][0]!=size){
             System.out.println("磁頭已經移到磁盤最外層:"+size);
         }
         
         System.out.println("第二次掃描:");
         for(int i=num-1;i>start;i--){             
             System.out.println("第二次掃描:"+"進程"+position[i][1]+"在磁道"+position[i][0]+"完成");
         }
     }   
}

為了直觀的感受一下各種算法的差別,我選了大概500個進程處理來比較它們的時間和平均尋道長度(現實中肯定不會有這麽多的待處理進程,不然炸了,只是為了比較),通過畫折線圖的方法進程比較,畫折線圖的實現過程在前面的文章中已經記錄過了,所以直接上結果:

技術分享圖片

技術分享圖片




磁盤調度算法FCFS、SSTF、SCAN、CSCAN詳解