java 驱动调度 电梯调度算法

来源:互联网 发布:百度贴吧加载数据失败 编辑:程序博客网 时间:2024/05/17 09:17
 

实验三  驱动调度

 

一、实习内容

模拟电梯调度算法,实现对磁盘的驱动调度。

二、实习目的

磁盘是一种高速、大容量、旋转型、可直接存取的存储设备。它作为计算机系统的辅助存储器,担负着繁重的输入输出任务,在多道程序设计系统中,往往同时会有若干个要求访问磁盘的输入输出请求等待处理。系统可采用一种策略,尽可能按最佳次序执行要求访问磁盘的诸输入输出请求,这就叫驱动调度,使用的算法称驱动调度算法。驱动调度能降低为若干个输入输出请求服务所需的总时间,从而提高系统效率。本实习要求学生模拟设计一个驱动调度程序,观察驱动调度程序的动态运行过程。通过实习使学生理解和掌握驱动调度的职能。

三、实习题目

模拟电梯调度算法,对磁盘进行移臂调度和旋转调度。

[提示]:

(1) 磁盘是可供多个进程共享的存储设备,但一个磁盘每个时刻只能为一个进程服务。当有进程在访问某个磁盘时,其它想访问该磁盘的进程必须等待,直到磁盘一次工作结束。当有多个进程提出输入输出请求而处于等待状态时,可用电梯调度算法从若干个等待访问者中选择一个进程,让它访问磁盘。选择访问者的工作由“驱动调度”进程来完成。

由于磁盘与处理器是可以并行工作的,所以当磁盘在为一个进程服务时,占有处理器的另一进程可以提出使用磁盘的要求,也就是说,系统能动态地接收新的输入输出请求。为了模拟这种情况,在本实习中设置一个“接收请求”进程。

“驱动调度”进程和“接收请求”进程能否占有处理器运行,取决于磁盘的结束中断信号和处理器调度策略。在实习中可用随机数来模拟确定这两个进程的运行顺序,以代替中断处理和处理器调度选择进程的过程。因而,程序的结构可参考图10-1。


图10-1  程序结构

(2) “接收请求”进程建立一张“请求I/O”表,指出等待访问磁盘的进程要求访问的物理地址,表的格式为:

 

进程名

柱面号

磁道号

物理记录号

 

M

M

 

 

M

M

 

M

M

 

M

M

 


假定某个磁盘组共有200个柱面,由外向里顺序编号(0-199),每个柱面上有20个磁道,编号为0-19,每个磁道分成8个物理记录,编号0-7。进程访问磁盘的物理地址可以用键盘输入的方法模拟得到。图10-2是“接收请求”进程的模拟算法。

图10-2  “接收请求”模拟算法

 

在实际的系统中必须把等待访问磁盘的进程排入等待队列,由于本实习模拟驱动调度,为简单起见,在实习中可免去队列管理部分,故设计程序时可不考虑“进程排入等待队列”的工作。

(3) “驱动调度”进程的功能是查“请求I/O”表,当有等待访问磁盘的进程时,按电梯调度算法从中选择一个等待访问者,按该进程指定的磁盘物理地址启动磁盘为其服务。

对移动臂磁盘来说,驱动调度分移臂调度和旋转调度。电梯调度算法的调度策略是与移动臂的移动方向和移动臂的当前位置有关的,所以每次启动磁盘时都应登记移臂方向和当前位置。电梯调度算法是一种简单而实际上用的驱动调度算法,这种调度策略总是优先选择与当前柱面号相同的访问请求,从这些请求中再选择一个能使旋转距离最短的等待访问者。如果没有与当前柱面号相同的访问请求,则根据移臂方向来选择,每次总是沿臂移动方向选择一个与当前柱面号最近的访问请求,若沿这个方向没有访问请求时,就改变臂的移动方向。这种调度策略能使移动臂的移动频率极小化,从而提高系统效率。用电梯调度算法实现驱动调度的模拟算法如图10-3。

(4) 图10-1中的初始化工作包括,初始化“请求I/O”表,置当前移臂方向为里移;置当前位置为0号柱面,0号物理记录。程序运行前可假定“请求I/O”表中已经有若干个进程等待访问磁盘。


在模拟实习中,当选中一个进程可以访问磁盘时,并不实际地启动磁盘,而用显示:“请求I/O”表;当前移臂方向;当前柱面号,物理记录号来代替图10-3中的“启动磁盘”这项工作。

图10-3  电梯调度模拟算法

四、实习报告

(1) 实习题目。

(2) 程序中使用的数据结构及其说明。

(3) 打印一份源程序并附上注释。

(4) 打印驱动调度进程每次选择访问请求的“请求I/O”表以及每次选中的进程名、访问的柱面号、物理记录号和当前移臂方向(用up代表里移,down代表外移)。打印格式为:

 

 

“请求I/O”表

 

 

进程名

柱面号

物理记录号

方向

 

--------------------------------------------------------------------------------------------------------------------------------------------------------------------------


package com.sau.news;

import java.util.LinkedList;
import java.util.Scanner;


public class Drive {

   
    private static void DeleteCourse(CourseClass cou) {
        for (Object obj : courselist) {
            CourseClass course = (CourseClass) obj;
            if (course.getId() == cou.getId() && course.getCylindernum() == cou.getCylindernum() && course.getTracknum() == cou.getTracknum() && course.getPhysicsnum() == cou.getPhysicsnum()) {
//                System.out.println("----------------dele  ------size---------------------" + courselist.size());
                courselist.remove(course);
                break;
            }
        }
//        System.out.println("--------------------delete----------end---2-----------");
    }

   
    public static class CourseClass {

        Integer id;//进程名(id)
        Integer cylindernum;//柱面号
        Integer tracknum;//磁道号
        Integer physicsnum;//物理记录号

       
        public Integer getCylindernum() {
            return cylindernum;
        }

       
        public void setCylindernum(Integer cylindernum) {
            this.cylindernum = cylindernum;
        }

        public Integer getId() {
            return id;
        }

        public void setId(Integer id) {
            this.id = id;
        }

       
        public Integer getPhysicsnum() {
            return physicsnum;
        }

       
        public void setPhysicsnum(Integer physicsnum) {
            this.physicsnum = physicsnum;
        }

       
        public Integer getTracknum() {
            return tracknum;
        }

       
        public void setTracknum(Integer tracknum) {
            this.tracknum = tracknum;
        }
    }

   
    public static class Arm {

       
        String direction = "up";
        Integer cylsite = 0;
        Integer physite = 0;

       
        public Integer getCylsite() {
            return cylsite;
        }

       
        public void setCylsite(Integer cylsite) {
            this.cylsite = cylsite;
        }

       
        public Integer getPhysite() {
            return physite;
        }

       
        public void setPhysite(Integer physite) {
            this.physite = physite;
        }

       
        public String getDirection() {
            return direction;
        }

       
        public void setDirection(String direction) {
            this.direction = direction;
        }
    }
   
    public static LinkedList courselist = new LinkedList();
   
//    public static CourseClass course = new CourseClass();
   
    public static Arm arm = new Arm();

   
    private static boolean CheakListNull() {
        boolean b = false;
        if (courselist.size() == 0) {
            b = true;
        }
        return b;
    }

   
    private static boolean CheakNowArm() {
        for (Object obj : courselist) {
            CourseClass coursetemp = (CourseClass) obj;
            if (coursetemp.getCylindernum() == arm.getCylsite() && coursetemp.getPhysicsnum() == arm.getPhysite() && coursetemp.getTracknum() == arm.getPhysite()) {
                System.out.println("经驱动调度后,当前运行的进程为:");
//                System.out.println("-------------------------cheaknowarm--------------------------");
                System.out.println("进程名:       柱面号        磁道号        物理记录号 ");
                System.out.println(coursetemp.getId() + "            " + coursetemp.getCylindernum() + "        " + coursetemp.getTracknum() + "            " + coursetemp.getPhysicsnum());
//                arm.setCylsite(course.getCylindernum());
//                arm.setDirection(0);//如果移动臂的当前位置有等待的进程,则不用修改移动臂的位置以及方向。
                courselist.remove(coursetemp);
                return true;
            }
        }
        return false;
    }

   
    private static LinkedList<CourseClass> FindSameCyl(LinkedList<CourseClass> courlist, Integer cyl) {
        LinkedList<CourseClass> list = new LinkedList<CourseClass>();
//        System.out.println("-------FindSameCyl------------------查找同一柱面号的-------------------------");
        for (Object obj : courlist) {
            CourseClass coursetemp = (CourseClass) obj;
            if (coursetemp.getCylindernum() == cyl) {
                list.add(coursetemp);
            }
        }
//        System.out.println("--------------查找同一柱面号的----------------list.size()-----------------------------"+list.size());
        return list;
    }

   
    private static boolean OutputOneCourse(CourseClass cou) {
        System.out.println("经驱动调度后,当前运行的进程为:");
//        System.out.println("------------------outputonecourse-------------------------");
        System.out.println("进程名:       柱面号        磁道号        物理记录号      移动方向");
        System.out.println(cou.getId() + "            " + cou.getCylindernum() + "        " + cou.getTracknum() + "            " + cou.getPhysicsnum() + "                   " + arm.getDirection());
        //记住当前的位置
        arm.setCylsite(cou.getCylindernum());
        arm.setPhysite(cou.getPhysicsnum());
        //删除进程记录
        DeleteCourse(cou);
//        System.out.println("------------------------------------" + courselist.size());
        return true;
    }

   
    private static boolean inputcourse() {
        CourseClass course = new CourseClass();
        Integer id = 0, cnum = 0, tnum = 0, pnum = 0;
        System.out.println("请输入进程的");
        System.out.println("进程名(id)  柱面号(0-199)磁道号(0-19)   物理记录号(0-7)");
        Scanner scan = new Scanner(System.in);
        id = scan.nextInt();
        cnum = scan.nextInt();
        tnum = scan.nextInt();
        pnum = scan.nextInt();
        boolean b = CheakReadyUser(id, cnum, tnum, pnum);
        if (b) {
            System.out.println("------已经被占用了---------");
        } else {
            course.setId(id);
            course.setCylindernum(cnum);
            course.setTracknum(tnum);
            course.setPhysicsnum(pnum);
            courselist.add(course);
//            System.out.println("----------------courselist.size()-----------" + courselist.size());
        }
        return b;

    }

   
    private static boolean CheakReadyUser(Integer id, Integer cyl, Integer track, Integer phy) {
        boolean b = false;
        for (Object obj : courselist) {
            CourseClass cou = (CourseClass) obj;
            if (cou.getId() == id) {
                System.out.println("该进程id已经被占用!");
                b = true;
                return b;
            } else {
                if (cou.getCylindernum() == cyl && cou.getTracknum() == track && cou.getPhysicsnum() == phy) {
                    System.out.println("该进程申请位置已经被占用!");
                    b = true;
                    return b;
                } else {
                    b = false;
                }
            }
        }
        return b;
    }

   
    private static void outcourselist() {
        System.out.println("等待的进程为:");
        System.out.println("进程名:       柱面号        磁道号        物理记录号 ");
        for (Object obj : courselist) {
            CourseClass cou = (CourseClass) obj;
            System.out.println(cou.getId() + "            " + cou.getCylindernum() + "        " + cou.getTracknum() + "            " + cou.getPhysicsnum());
            System.out.println("输出完毕!");
        }
    }

   
    private static LinkedList<CourseClass> BigThen() {
        LinkedList<CourseClass> list = new LinkedList<CourseClass>();
        for (Object obj : courselist) {
            CourseClass course = (CourseClass) obj;
            if (course.getCylindernum() > arm.getCylsite()) {
                list.add(course);
            }
        }
        return list;
    }

   
    private static LinkedList<CourseClass> LittleThen() {
        System.out.println("------------------查找臂当前柱面小的!-----------------------------");
        LinkedList<CourseClass> list = new LinkedList<CourseClass>();
        for (Object obj : courselist) {
            CourseClass course = (CourseClass) obj;
            if (course.getCylindernum() < arm.getCylsite()) {
                list.add(course);
            }
        }
        return list;
    }

   
    private static void rundrive() {
        //检查进程链表是否为空。如果为空则返回函数开始
        boolean CheakListNull_b = CheakListNull();
        if (CheakListNull_b) {
            System.out.println("等待的进程链为空,驱动调度失败!");
            return;
        } else {
//             检查移动臂当前柱位置是否有等待的进程,如果当前位置有等待的进程,则直接输出
            boolean CheakNowArm_b = CheakNowArm();
            if (CheakNowArm_b) {
                System.out.println("--------------检查当前位置--------------------------");
                //当前驱动已经调度一次,返回主函数
                return;
            } else {
//                查找同一层的进程
                LinkedList<CourseClass> samecyllist = FindSameCyl(courselist, arm.getCylsite());
//                System.out.println("--------------查找同一个柱面号的--------------------------");
                //如果同一柱面号中有或有几个进程,找出其中最近的一个并返回
                if (samecyllist.size() != 0) {
//                    System.out.println("--------samecyllist--------------" + samecyllist.size());
                    //找出同一个柱面号中最近的一个进程,并返回
                    CourseClass cour = FindSameCylNearest(samecyllist);
//                    System.out.println("--------------查找同一个柱面号中最适合的进程输出------- 向上找时-------------------");
                    //输出同一柱面号中最适合的那个进程,输出过程中记住当前的移动臂位置
                    if (cour != null) {
                        OutputOneCourse(cour);
                    }
                    return;
                } else {
                    //程序运行到这里表示在同一个住面上已经没有等待进程了,这里开始调用电梯调度算法。
                    System.out.println("现在进行驱动的电梯调度算法!");
                    //电梯调度算法
                    FleedDiver();
                }
            }
        }
    }

   
    private static Integer FindSmallestCylnum(LinkedList<CourseClass> biglist) {
        Integer small = 200;
        for (Object obj : biglist) {
            CourseClass coursetemp = (CourseClass) obj;
            if (Math.abs(coursetemp.getPhysicsnum() - arm.getPhysite()) < small && coursetemp.getCylindernum() >= arm.getCylsite()) {
                small = coursetemp.getCylindernum();
            }
        }
        return small;
    }

   
    private static Integer FindBiggestCylnum(LinkedList<CourseClass> littlelist) {
        Integer small = 200;
        for (Object obj : littlelist) {
            CourseClass coursetemp = (CourseClass) obj;
            if (Math.abs(coursetemp.getPhysicsnum() - arm.getPhysite()) < small && coursetemp.getCylindernum() <= arm.getCylsite()) {
                small = coursetemp.getCylindernum();
            }
        }
        return small;
    }

   
    private static CourseClass FindOneOfSameCly(LinkedList<CourseClass> list) {
//        System.out.println("-------------------------FindOneOfSameCly-----------------------------------");
        CourseClass temp = new CourseClass();
        Integer min = 10;
        for (Object obj : list) {
            CourseClass cou = (CourseClass) obj;
            if (Math.abs(cou.getPhysicsnum() - arm.getPhysite()) < min) {
                min = Math.abs(cou.getPhysicsnum() - arm.getPhysite());
                temp.setId(cou.getId());
                temp.setCylindernum(cou.getCylindernum());
                temp.setTracknum(cou.getTracknum());
                temp.setPhysicsnum(cou.getPhysicsnum());
            }
        }
        return temp;
    }

   
    private static CourseClass FindMoreBigLittle(LinkedList<CourseClass> biglist) {
        System.out.println("-------------------FindMoreBigLittle-------------------------------");
        //先查找出比当前柱面号大的最小的那个柱面号的值
        Integer small = FindSmallestCylnum(biglist);
        //查找出统一个柱面号中的进程
        LinkedList<CourseClass> templist = FindSameCyl(biglist, small);
        //诈骗出应该运行的那个进程
        CourseClass right = FindOneOfSameCly(templist);

        return right;
    }

   
    private static CourseClass FindMoreLittleBig(LinkedList<CourseClass> littlelist) {
        //先查找出比当前柱面号大的最小的那个柱面号的值
        Integer small = FindBiggestCylnum(littlelist);
        //查找出统一个柱面号中的进程
        LinkedList<CourseClass> templist = FindSameCyl(littlelist, small);
        //诈骗出应该运行的那个进程
        CourseClass right = FindOneOfSameCly(templist);
        return right;
    }

   
    private static CourseClass FindSameCylNearest(LinkedList<CourseClass> samecyllist) {
        Integer min = 9;
        CourseClass cou = new CourseClass();
        System.out.println("-------------------samecyllist.size()---------------------" + samecyllist.size());
        for (Object obj : samecyllist) {
            CourseClass coursetemp = (CourseClass) obj;
            System.out.println("--------------FindSameCylNearest--------------------------");
            if (Math.abs(coursetemp.getPhysicsnum() - arm.getPhysite()) < min) {
                cou.setId(coursetemp.getId());
                cou.setCylindernum(coursetemp.getCylindernum());
                cou.setPhysicsnum(coursetemp.getPhysicsnum());
                cou.setTracknum(coursetemp.getTracknum());
            }
        }
        return cou;

    }

   
    private static void FleedDiver() {
        if (arm.getDirection().equals("up")) {
//            判断是否有比当前柱面号更大的进程
            LinkedList<CourseClass> biglist = BigThen();
            if (biglist.size() != 0) {
                System.out.println("-----FleedDiver----------biglist.size()----------------------" + biglist.size());
                CourseClass cour = FindMoreBigLittle(biglist);
                //记录移动臂的方向
                arm.setDirection("up");
                //输出一个进程
                OutputOneCourse(cour);
                // 查找出比当前进进程大但是最小的那个适合输出的进程,返回

            } else {
//               没有将查找向反向
//               同时开始查找比当前柱面号小的最大的进程
//               改变移动臂的方向,向下
                arm.setDirection("down");
                LinkedList<CourseClass> littlelist = LittleThen();
                if (littlelist.size() != 0) {
                    CourseClass cour = FindMoreLittleBig(littlelist);
                    //输出一个进程
                    OutputOneCourse(cour);
                }
            }
        } else {
            LinkedList<CourseClass> littlelist = LittleThen();
            if (littlelist.size() != 0) {
                CourseClass cour = FindMoreLittleBig(littlelist);
//                System.out.println("---------------------向下查找--------------down-----------------");
                //输出一个进程
                arm.setDirection("dowm");
                OutputOneCourse(cour);
            } else {
                LinkedList<CourseClass> biglist = BigThen();
                if (biglist.size() != 0) {
                    CourseClass cour = FindMoreBigLittle(biglist);
                    //记录移动臂的方向
                    arm.setDirection("up");
                    //输出一个进程
                    OutputOneCourse(cour);
                    // 查找出比当前进进程大但是最小的那个适合输出的进程,返回
                }
            }
        }
    }

   
    public static void main(String[] args) {
        Integer num = 0, order = 0;
        System.out.println("程序即将运行,输入你想提前创建的几个等待进程:");
        Scanner scan = new Scanner(System.in);
        num = scan.nextInt();
        for (int i = 0; i < num; i++) {
            inputcourse();
        }
        //将移动臂的初始位置,初始方向,设定
        arm.setDirection("up");
        arm.setPhysite(0);
        arm.setCylsite(0);

        System.out.println("输入命令: 0--退出  1--驱动调度   2--添加进程请求   3--输出等待进程列表");
        order = scan.nextInt();
        while (order != 0) {
            switch (order) {
                case 0:
                    break;
                case 1:
                    rundrive();
                    break;
                case 2:
                    inputcourse();
                    break;
                case 3:
                    outcourselist();
                    break;
            }
            System.out.println();
            System.out.println("输入命令: 0--退出  1--驱动调度   2--添加进程请求   3--输出等待进程列表");
            order = scan.nextInt();
        }
        System.out.println("程序运行结束!\n");
    }
}