磁盘调度之扫描类算法

1、扫描(SCAN)算法

1)进程“饥饿”现象

SSTF算法虽然能获得较好的寻道性能,但却可能导致某个进程发生“饥饿”现象。因为只要不断有新进程的请求到达,且其所要访问的磁道与磁头当前所在磁道的距离较近,这种新进程的I/O请求必然优先满足。对SSTF算法略加修改后所形成的SCAN算法,即可防止老进程出现“饥饿”现象。

2)SCAN算法

该算法不仅考虑到欲访问的磁道与当前磁道间的距离,更优先考虑的是磁头当前的移动方向。例如,当磁头正在自里向外移动时,SCAN算法所考虑的下一个访问对象,应是其欲访问的磁道既在当前磁道之外,又是距离最近的。这种自里向外地访问,直至再无更外的磁道需要访问时,才将磁臂换向为自外向里移动。这是,同样也是每次选择这样的进程来调度,即要访问的磁道在当前位置内距离最近者,这样,磁头又逐步地从外向里移动,直至再无更里面的磁道要访问,从而避免了出现“饥饿”现象。由于在这种算法中磁盘移动的规律颇似电梯的运行,因而又常称之为电梯调度算法。下图示出了按SCAN算法对9个进程进行调度及磁头移动的情况。
在这里插入图片描述

2、循环扫描(CSCAN)算法

SCAN算法既能获得较好的寻道性能,又能防止“饥饿”现象,故被广泛应用于大、中、小型机器和网络中的磁盘调度。但SCAN也存在这样的问题:当磁头刚从里向外移动而越过了某一磁道时,恰好又有一进程请求访问此磁道,这时,该进程必须等待,待磁头继续从里向外,然后再从外向里扫描完所有要访问的磁道后,才处理该进程的请求,致使该进程的请求被大大地推迟。为了减少这种延迟,CSCAN算法规定磁头单向移动,例如,只是自里向外移动,当磁头移到最外的磁道并访问后,磁头立即返回到最里的欲访问的磁道,亦即将最小磁道号紧接着最大磁道号构成循环,进行循环扫描。采用循环扫描方式后,上述请求进程的请求延迟将从原来的2T减为T+Smax,其中,T为由里向外或由外向里单向扫描完要访问的磁道所需的寻道时间,而Smax是将磁头从最外面被访问的磁道直接移到最里面欲访问的磁道(或相反)的寻道时间。下图示出了CSCAN算法对9个进程调度的次序及每次磁头移动的距离。
在这里插入图片描述

3、NStepSCAN和FSCAN调度算法

1)NStepSCAN算法

在SSTF,SCAN及CSCAN几种调度算法中,都可能会出现磁臂停留在某处不动的情况,例如,有一个或几个进程对某一磁道有较高的访问频率,即这个(些)进程反复请求对某一磁道的I/O操作,从而垄断了整个磁盘设备。我们把这一现象称为“磁臂粘着”(Armstickiness)。在高密度磁盘上容易出现此情况。N步SCAN算法是将磁盘请求队列分成若干个长度为N的子队列,磁盘调度将按FCFS算法依次处理这些子序列。而每处理一个队列时又是按SCAN算法,对一个队列处理完毕后,再处理其他队列。当正在处理某子序列时,如果又出现新的磁盘I/O请求,便将新请求进程放入其他队列,这样就可避免出现粘着现象。当N值取得很大时,会使N步扫描法的性能接近于SCAN算法的性能;当N=1时,N步SCAN算法便蜕化为FCFS算法。

2)FSCAN算法

FSCAN算法实质上是N步SCAN算法的简化,即FSCAN只将磁盘请求队列分成两个子队列。一个是当前所有请求磁盘I/O的进程形成的队列,由磁盘调度按SCAN算法进行处理。在扫描期间,将新出现的所有请求磁盘I/O的进程,放入另一个等待处理的请求队列。这样,所有的新请求都将被推迟到下一次扫描时处理。

  • 7
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
磁盘调度算法是计算机操作系统中的重要算法之一,它可以优化磁盘上数据的读取和写入。其中,n步扫描算法是一种常见的磁盘调度算法,它可以在一定程度上降低磁盘的寻道时间。 以下是一个简单的 Java 实现: ```java import java.util.ArrayList; import java.util.Collections; public class DiskScheduler { public static void main(String[] args) { int[] requests = { 176, 79, 34, 60, 92, 11, 41, 114 }; int head = 50; int n = 4; System.out.println("Original request order: "); for (int i = 0; i < requests.length; i++) { System.out.print(requests[i] + " "); } ArrayList<Integer> left = new ArrayList<Integer>(); ArrayList<Integer> right = new ArrayList<Integer>(); // 将请求按照距离磁头的距离分成左右两个部分 for (int i = 0; i < requests.length; i++) { if (requests[i] < head) { left.add(requests[i]); } else { right.add(requests[i]); } } // 对左右两个部分分别按照距离磁头的距离排序 Collections.sort(left); Collections.sort(right); int totalMovement = 0; int current = head; // 先扫描右边的请求 for (int i = 0; i < right.size(); i++) { int next = right.get(i); totalMovement += Math.abs(next - current); current = next; } // 如果左边有请求,需要反向扫描左边的请求 if (left.size() > 0) { totalMovement += Math.abs(current - 0); current = 0; // 从右向左扫描左边的请求 for (int i = right.size() - 1; i >= 0; i--) { int next = right.get(i); totalMovement += Math.abs(next - current); current = next; } // 扫描左边的请求 for (int i = 0; i < left.size(); i++) { int next = left.get(i); totalMovement += Math.abs(next - current); current = next; } } System.out.println("\nTotal head movement: " + totalMovement); } } ``` 以上代码中,我们以数组的形式定义了一组磁盘访问请求。接着,我们将请求按照距离磁头的距离分成左右两个部分,并对它们分别进行排序。然后,我们从右向左扫描右边的请求,再从左向右扫描左边的请求,计算出总的磁头移动距离。最后,我们输出磁头移动距离的结果。 注意,在实际应用中,我们需要根据不同的情况选择不同的磁盘调度算法,并且需要考虑到磁盘的实际特性,如磁盘的转速、缓存等等。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值