实验二 磁盘调度
前言
-
参考教材《操作系统 第四版》汤小丹
-
因为实验要求为了更好地模拟和评价算法的性能,随机产生需寻道的磁道序列,以磁道序列的首磁道为磁头的当前位置;在SCAN算法中,允许用户指定当前寻道方向;随机产生数据不方便对比,所以做了两份代码(一种随机产生磁道序列以磁道序列的首磁道为磁头的当前位置(这里命名为A)即实验内容,一种自定义磁道序列自定义磁头位置(这里命名为B)),完整代码放在文末了,方便对比
-
SCAN算法做出了两种方法,分别写在了固定磁头位置和自定义磁头位置
-
虽然只做了三种,循环算法大同小异,搞懂前三个,其它算法很好编写
实验目的
编程模拟实现磁盘调度的常用算法或调试分析相关磁盘调度程序,加深对磁盘调度常用算法的理解和实现技巧
实验内容
1.自定义磁盘调度相关的数据结构
2.依据先来先服务算法(FCFS)、最短寻道优先算法(SSTF)、扫描(SCAN,也称电梯)算法的原理,编写对应函数,模拟系统的磁盘调度服务;
3.为了更好地模拟和评价算法的性能,随机产生需寻道的磁道序列,以磁道序列的首磁道为磁头的当前位置;在SCAN算法中,允许用户指定当前寻道方向;
4.统计以上算法总寻道次数和平均寻道距离;
比较/分析以上算法的寻道性能,并作出自己的评价
实验步骤
冒泡排序
先写一个冒泡排序,在后面调用会使用到
// 冒泡排序(从小到大)
public static void SortA(int[] list){
for (int i = 0; i < list.length - 1; i++) {
for (int j = 0; j < list.length - 1 - i; j++) {
if (list[j] > list[j + 1]) {
int temp = list[j];
list[j] = list[j + 1];
list[j + 1] = temp;
}
}
}
}
// 冒泡排序(从大到小)
public static void SortB(int[] list) {
for (int i = 0; i < list.length - 1; i++) {
for (int j = 0; j < list.length - 1 - i; j++) {
if (list[j] < list[j + 1]) {
int temp = list[j];
list[j] = list[j + 1];
list[j + 1] = temp;
}
}
}
}
先来先服务FCFS
A
// 先来先服务FCSFS,即根据磁盘访问的先后次序进行调度,遍历list数组即可,所以不做赘述
private static void FCFS(int[] list) {
System.out.println("磁道开始位置为" + list[0]);
int num = 0;// 变量num记录寻道距离
for (int j = 0; j < list.length - 1; j++) {
num += Math.abs(list[j + 1] - list[j]);
}
System.out.println("磁盘扫描序列为:" + Arrays.toString(list));
System.out.println("寻道次数:" + num);
double w = ((float) num / (float) list.length);
System.out.println("平均寻道距离:" + w);
}
B
// 先来先服务FCSFS,即根据磁盘访问的先后次序进行调度,遍历list数组即可,所以不做赘述
private static void FCFS(int[] list) {
int i = 0;
System.out.println("请输入磁头初始位置");
Scanner sc = new Scanner(System.in);
i = sc.nextInt();
int num = 0;// 变量num记录寻道距离
num = Math.abs(i - list[0]);
for (int j = 0; j < list.length - 1; j++) {
num += Math.abs(list[j + 1] - list[j]);
}
System.out.println("磁盘扫描序列为:" + Arrays.toString(list));
System.out.println("寻道次数" + num);
double w = ((float) num / (float) list.length);
System.out.println("平均寻道距离" + w);
}
最短寻道时间优先SSTF
// 最短路径算法SSTF,即访问下一个磁道前,先计算一次当前磁头到访问各个磁道的距离
private static void SSTF(int[] list) {
int[] list1=new int[list.length];//因为下面修改了list,再次运行算法3时,list数组已经被修改,所以这里把值传给list1
System.arraycopy(list,0, list1, 0, list.length);
int i = list1[0];// 变量i记录当前磁头位置
System.out.println("磁道开始位置为" + list1[0]);
int num = 0;// num记录总寻道距离
int[] k = new int[list1.length];// k数组记录访问的每一个磁道到磁头距离
int[] templist = new int[list1.length];// 将结果保存在templist[]中
for (int a = 0; a < list1.length; a++) {
// j循环遍历出每一个访问的磁道到当前磁头的距离保存在k数组中
for (int j = 0; j < list1.length; j++) {
k[j] = Math.abs(list1[j] - i);
}
// 将k数组赋值给temp数组,对temp数组冒泡排序
int[] temp = new int[k.length];
for (int j = 0; j < k.length; j++) {
temp[j] = k[j];
}
SortA(temp);
int j = temp[0];// 找到磁头到下一个磁道距离最小的为temp[0]
// 循环遍历找到temp[0]在list磁道序列数组中的位置
for (int t = 0; t < k.length; t++) {
// if语句找到list[t]到当前磁头最近
if (k[t] == j) {
i = list1[t];// 变量i记录磁头位置
templist[a] = i;// 将结果存入templist数组中
list1[t] = 999999;// 将第g个磁道号设为999999,可以理解为权重设为99999,这样他在下一次遍历,在k数组中总是最大
break;
}
}
num += j;
}
System.out.println("磁盘扫描序列为:" + Arrays.toString(templist));
System.out.println("寻道次数:" + num);
double w = ((float) num / (float) list.length);
System.out.println("平均寻道距离:" + w);
}
B
// 最短路径算法SSTF,即访问下一个磁道前,先计算一次当前磁头到访问各个磁道的距离
private static void SSTF(int[] list) {
int i = 0;// 变量i记录当前磁头位置
int num = 0;// num记录总寻道距离
int[] templist = new int[list.length];// 将结果保存在templist[]中
int[] k = new int[list.length];// k数组记录访问的每一个磁道到磁头距离
System.out.println("请输入磁头初始位置");
Scanner sc = new Scanner(System.in);
i = sc.nextInt();
for (int a = 0; a < list.length; a++) {
// j循环遍历出每一个访问的磁道到当前磁头的距离保存在k数组中
for (int j = 0; j < list.length; j++) {
k[j] = Math.abs(list[j] - i);
}
// 将k数组赋值给temp数组,对temp数组冒泡排序
int[] temp = new int[k.length];
for (int j = 0; j < k.length; j++) {
temp[j] = k[j];
}
SortA(temp);
int j = temp[0];// 找到磁头到下一个磁道距离最小的为temp[0]
// 循环遍历找到temp[0]在list磁道序列数组中的位置
for (int t = 0; t < k.length; t++) {
// if语句找到list[t]到当前磁头最近
if (k[t] == j) {
i = list[t];// 变量i记录磁头位置
templist[a] = i;// 将结果存入templist数组中
list[t] = 999999;// 将第g个磁道号设为999999,可以理解为权重设为99999,这样他在下一次遍历,k数组中总是最大
break;
}
}
num += j;
}
System.out.println("磁盘扫描序列为:" + Arrays.toString(templist));
System.out.println("寻道次数:" + num);
double w = ((float) num / (float) list.length);
System.out.println("平均寻道距离:" + w);
}
扫描算法SCAN
写完扫描算法准备关机的时候,突然想到了另一种排序方法,B的第42行else语句中,好像可以修改修改。所以对A进行了修改。对A简单修改还可以实现CSCAN循环扫描算法,我认为A中的算法更容易理解其中的原理,所以下面着重解释!
A
/*
* 扫描算法SCAN 磁盘的0磁道在最外圈 扫描算法又叫电梯算法,即按从小到大或从大到小的顺序去依次访问磁道。
* 所以这里分两种情况,1.寻道从内向外(从大到小) 2.寻道从外向内(从小到大)
*
*
* 1.若当前磁头位置大于请求序列中最大者 2.若当前磁头位置小于请求序列中最小者 3.若当前磁道号大于请求序列中最小者且小于最大者
* 这里用同一个函数去解决三种情况
*/
private static void SCAN(int[] list) {
int[] list1=new int[list.length];//因为下面修改了list,再次运行算法3时,list数组已经被修改,所以这里把值传给list1
System.arraycopy(list,0, list1, 0, list.length);
Scanner sc = new Scanner(System.in);
int k = list1[0];// 变量i记录当前磁头位置
int tempk1 = 0;
int tempk2 = 0;
int flag=1;
int num = 0;// num记录总寻道距离
int[] templist = new int[list1.length];// 将访问顺序存入templist中
System.out.println("磁道开始位置为:" + list1[0]);
//while中先计算出磁道访问的顺序
while (true) {
System.out.println("1.磁头从外向内 2.磁头从内向外");
int choice = sc.nextInt();
if (choice == 1) {
flag