操作系统之磁盘调度——SCAN实例讲解

操作系统之进程调度——优先权法和轮转法(附上样例讲解)
操作系统之银行家算法—详解流程及案例数据
操作系统之多线程编程—读者优先/写者优先详解
操作系统之存储管理——FIFO算法和LRU算法
操作系统之磁盘调度——SCAN实例讲解

一、实验目的:
磁盘是高速、大容量、旋转型、可直接存取的存储设备。它作为计算机系统的辅助存储器,担负着繁重的输入输出工作,在现代计算机系统中往往同时会有若干个要求访问磁盘的输入输出要求。系统可采用一种策略,尽可能按最佳次序执行访问磁盘的请求。由于磁盘访问时间主要受寻道时间T的影响,为此需要采用合适的寻道算法,以降低寻道时间。本实验要求学生模拟设计一个磁盘调度程序,观察调度程序的动态运行过程。通过实验让学生理解和掌握磁盘调度的职能。
二、实验内容:
模拟电梯调度算法,对磁盘进行移臂操作
三、提示及要求:
1、假设磁盘只有一个盘面,并且磁盘是可移动头磁盘。
2、磁盘是可供多个进程共享的存储设备,但一个磁盘每个时刻只能为一个进程服务。当有进程在访问某个磁盘时,其它想访问该磁盘的进程必须等待,直到磁盘一次工作结束。当有多个进程提出输入输出请求而处于等待状态时,可用电梯调度算法从若干个等待访问者中选择一个进程,让它访问磁盘。为此设置“驱动调度”进程。
3、由于磁盘与处理器是并行工作的,所以当磁盘在为一个进程服务时,占有处理器的其它进程可以提出使用磁盘(这里我们只要求访问磁道),即动态申请访问磁道,为此设置“接受请求”进程。
4、为了模拟以上两个进程的执行,可以考虑使用随机数来确定二者的允许顺序,程序结构图参考附图:
5、“接受请求”进程建立一张“进程请求I/O”表,指出等待访问磁盘的进程要求访问的磁道,表的格式如下:
| 进程名 | 要访问的磁道 |
|进程id| 磁道号:|
6、 “磁盘调度”的功能是查“请求I/O”表,当有等待访问的进程时,按电梯调度算法(SCAN算法)从中选择一个等待访问的进程,按其指定的要求访问磁道。SCAN算法参考课本第九章。算法模拟框图略。
7、附图中的“初始化”工作包括:初始化“请求I/O”表,设置置当前移臂方向;当前磁道号。并且假设程序运行前“请求I/O”表中已有若干进程(4~8个)申请访问相应磁道。
四、实验报告:
1、实验题目。
2、程序中用到的数据结构及其说明。
3、打印源程序并附注释。
4、实验结果内容如下:打印“请求I/O”表,当前磁道号,移臂方向,被选中的进程名和其要求访问的磁道,看是否体现了电梯调度(SCAN)算法。体会与问题。
五、 附图:
操作系统之磁盘调度——SCAN实例讲解

上面就是实验要求。
本实验的核心就是对SCAN算法的理解,SCAN被称为梯度算法。因为它不仅兼顾距离的远近还兼顾方向性。
Scan算法思想大致为:
当设备无访问请求时,磁头不动;当有访问请求时,磁头按一个方向移动,在移 [2] 动过程中对遇到的访问请求进行服务,然后判断该方向上是否还有访问请求,如果有则继续扫描;否则改变移动方向,并为经过的访问请求服务,如此反复。如下图所示:
操作系统之磁盘调度——SCAN实例讲解
这大致就是流程,当然,你可以动态的增加io请求(接受请求)。
附上代码:

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Scanner;

public class 磁盘调度 {
	private static void getstatus(List<io>list) {
		// TODO 自动生成的方法存根
		System.out.println("进程id:    磁道:    是否调度?:");
		for(int i=0;i<list.size();i++)
		{
			System.out.println(list.get(i).id+"    "+list.get(i).cidao+"    "+list.get(i).isdiaodu);
		}		
	}
	private static void diaodu(List<io> list, int index, int cidao) {
		if(index==1)//向左面
		{
			int mid=0;
			for(int i=0;i<=list.size();i++)
			{
				if(list.get(i).cidao>cidao&&list.get(i).isdiaodu==false)
				{
					mid=i-1;break;
				}
			}
			while(mid>=0)
			{
				if(list.get(mid).isdiaodu==false)
				{
					io io=list.get(mid);
					io.isdiaodu=true;
					System.out.println("进程"+io.id+" 磁道:"+io.cidao+" 已经调度");					
				}
				mid--;
			}
			mid++;
			while(mid<list.size())
			{
				if(list.get(mid).isdiaodu==false)
				{
					io io=list.get(mid);
					io.isdiaodu=true;
					System.out.println("进程"+io.id+" 磁道:"+io.cidao+" 已经调度");					
				}
				mid++;
			}
		}
		else
		{
			int mid=list.size()-1;
			for(int i=0;i<list.size();i++)
			{
				if(list.get(i).cidao>cidao&&list.get(i).isdiaodu==false)
				{
					mid=i;break;
				}
			}
			while(mid<list.size())
			{
				if(list.get(mid).isdiaodu==false)
				{
					io io=list.get(mid);
					io.isdiaodu=true;
					System.out.println("进程"+io.id+" 磁道:"+io.cidao+" 已经调度");					
				}
				mid++;
			}
			mid--;
			while(mid>=0)
			{
				if(list.get(mid).isdiaodu==false)
				{
					io io=list.get(mid);
					io.isdiaodu=true;
					System.out.println("进程"+io.id+" 磁道:"+io.cidao+" 已经调度");					
				}
				mid--;
			}
			
		}
	}
	public static void main(String[] args) {
		// TODO 自动生成的方法存根
		Scanner sc=new Scanner(System.in);
		System.out.println("请输入访问磁盘的进程数量");
		int n=sc.nextInt();
		System.out.println("请输入访问进程的id和磁道号");
		List<io>list=new ArrayList<>();
		for(int i=0;i<n;i++)
		{
			int id=sc.nextInt();int cidao=sc.nextInt();
			io io=new io(id, cidao);
			list.add(io);
		}
		list.sort(compare);
		while(true)
		{
			System.out.println("输入0-1的随机数,小于0.5及开始磁盘调度");
			double a=sc.nextDouble();
			if(a<0.5)
			{
				System.out.print("当前队列磁道为:");
				for(int j=0;j<list.size();j++)
				{
					if(list.get(j).isdiaodu==false)
					System.out.print(list.get(j).cidao+" ");
				}
				System.out.println();
				System.out.println("请输入当前磁道");
				int cidao=sc.nextInt();
				System.out.println("请输入方向编号\n1:向左\n2:向右");
				{
					int team=sc.nextInt();
					 diaodu(list,team,cidao);
					getstatus(list);
				}
			}
			else {
				System.out.println("请输入新的进程id和磁道号");
				int id=sc.nextInt();
				int cidao=sc.nextInt();
				list.add(new io(id, cidao));
				list.sort(compare);
			}
			System.out.println("是否继续?Y/N");
			String str=sc.next();
			if(!str.equals("Y")) {System.exit(0);}
		}
		
	}
	
	static Comparator<io>compare=new Comparator<io>(
			) {

				@Override
				public int compare(io o1, io o2) {
					// TODO 自动生成的方法存根
					return o1.cidao-o2.cidao;
				}
	};
	static class io
	{
		int id;
		int cidao;
		boolean isdiaodu;
		public io(int id,int cidao)
		{
			this.id=id;
			this.cidao=cidao;
		}
	}
}

测试数据:

操作系统之磁盘调度——SCAN实例讲解

操作系统之磁盘调度——SCAN实例讲解
若有错误的地方,还请大神指正。