一、实习内容
模拟电梯调度算法,实现对磁盘的驱动调度。
二、实习目的
磁盘是一种高速、大容量、旋转型、可直接存取的存储设备。它作为计算机系统的辅助存储器,担负着繁重的输入输出任务,在多道程序设计系统中,往往同时会有若干个要求访问磁盘的输入输出请求等待处理。系统可采用一种策略,尽可能按最佳次序执行要求访问磁盘的诸输入输出请求,这就叫驱动调度,使用的算法称驱动调度算法。驱动调度能降低为若干个输入输出请求服务所需的总时间,从而提高系统效率。本实习要求学生模拟设计一个驱动调度程序,观察驱动调度程序的动态运行过程。通过实习使学生理解和掌握驱动调度的职能。
三、实习题目
模拟电梯调度算法,对磁盘进行移臂调度和旋转调度。
[提示]:
(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
FindSameCyl(LinkedList
courlist, Integer cyl) {
LinkedList list = new
LinkedList();
// 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;