《操作系统》——硬盘扫描问题的算法实现

《操作系统》课程实验(五)

——生产者消费者同步问题的算法实现

磁盘是可供多个进程共享的设备,当有多个进程都要求访问磁盘是,应采用一种最佳调度算法,以使各进程对磁盘的平均访问时间最小。目前最成用的磁盘调度算法有先来先服务(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. 实验截图

 

 

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值