COA5 磁盘
- 外部存储器——磁盘的模拟。
- 工作主要集中在模拟磁头结构
- Disk.java # 磁盘类,需要修改
- Scheduler.java # 磁盘调度算法类,需要修改
- 注:磁盘存储容量 = 磁头数 × 磁道(柱面)数 × 每道扇区数 × 每扇区字节数
- 读写方法中接收的addr参数,是二进制表示的该数据起始位置在虚拟磁盘文件中的字节数
- seek方法表示每次数据读写之前将磁头移动到指定位置,addPoint表示将磁头往后移动一个字节
一、 Disk
- 结合read和write方法的源码,理解seek方法和addPoint方法在其中起到什么作用,然后实现这两个方法。
- 注意,由于我们规定该磁盘有8个磁头即8个盘面,所以每个盘面的大小为8MB。在不同盘面上,磁头的位置都是相同的(具体可以看ppt上的图)。因此,在我们的模拟规则下,第0个字节、第8MB个字节、第16MB个字节(以此类推),它们的磁头位置都应该是相同的。
1. seek
- 用来将磁盘的指针移动到指定的 addr 地址
- 将指针point移动到start位置
- 计算start所在的扇区数——指针sector
- 当前字节数 / 每扇区字节数
- 计算start所在的磁道数——指针track
- 当前扇区数 / 每磁道扇区数
1 | this.point=start; |
2. addPoint
- 将磁头往后移动一个字节,
point++
。 - 如果指针移动到当前扇区的末尾(512字节),则重置point为0,并移动到下一个扇区。
- point=0
- sector++
- 如果扇区移动到当前磁道的末尾(64个扇区),则重置扇区并移动到下一个磁道。
- sector=0
- track++
- 如果磁道移动到磁盘的末尾(磁道数),则重置磁道号为0,即磁头回到磁盘的起始位置。
- track=0;
1 | this.point++; |
二、Scheduler
- 每个方法都会传入磁头初始磁道号与请求访问的磁道号数组
- 需要计算出平均寻道长度并返回
1.先来先服务算法FCFS
- 先请求的先进行
- 初始化
- 总路程为0
- 当前磁道号为start
- 遍历整个request
- 总路程累加
- 当前磁道号变化
- 最后返回 总路程 / 请求length
1 | public double FCFS(int start, int[] request) { |
2.最短寻道时间优先算法 SSTF
- 优先处理起始位置与当前磁头位置最接近的读写任务
- 初始化
- sumDistance:总寻道距离,初始为0。
- currentTrack:当前磁头所在的磁道号,初始为 start。
- n:请求数组的长度。
- visited:记录每个请求是否被访问过,初始为 false。
- 遍历请求:
- 外层循环:遍历 n 次,每次找到一个最接近当前磁头位置的请求。
- 内层循环:遍历所有请求,找到距离当前磁头位置最近且未被访问过的请求。
- 更新状态:
- 标记找到的请求visited为true。
- 累加最短距离到 sumDistance。
- 更新 currentTrack 为找到的请求位置。
- 返回平均寻道长度:
- 返回 sumDistance 除以请求数组的长度。
1 | public double SSTF(int start, int[] request) { |
3. 扫描算法 SCAN
- 总是按照一个方向进行磁盘调度,直到该方向上的边缘,然后改变方向
- 磁道总数,这个数字需要与Disk类中的TRACK_NUM保持一致。(256)
Arrays.sort(request);
对请求数组进行升序排序
- 初始化:
- sumDistance:总寻道距离,初始为0。
- n:请求数组的长度。
- 对请求数组进行升序排序:Arrays.sort(request);。
- 判断初始移动方向:(题上说了true是增大方向)
- 如果
direction
为 true,表示初始移动方向是增大方向。- start <= request[0],表示磁头在最小请求之前,直接移动到最大请求位置。
- 易错:不是直接移动到磁道最后!
- start 在请求数组中间,先移动到磁道最大位置(
255
),再返回到最小请求位置。
- start <= request[0],表示磁头在最小请求之前,直接移动到最大请求位置。
- 如果 direction 为 false,表示初始移动方向是减小方向。
- start >= request[n - 1],表示磁头在最大请求之后,直接移动到最小请求位置。
- start 在请求数组中间,先移动到磁道最小位置,再返回到最大请求位置。
- 如果
- 返回平均寻道长度:
- 返回 sumDistance 除以请求数组的长度。
1 | public double SCAN(int start, int[] request, boolean direction) { |
4. C-SCAN算法:默认磁头向磁道号增大方向移动
- 只有磁头朝某个方向移动时才会响应请求,移动到边缘后立即让磁头返回起点,返回途中不做任何处理
- 初始化
- sumDistance:总寻道距离,初始为0。
- currentTrack:当前磁头所在的磁道号,初始为 start。
- n:请求数组的长度。
- 对请求数组进行升序排序:Arrays.sort(request);。
- 查找当前磁头位置:
- 使用 Arrays.binarySearch(request, currentTrack) 查找当前磁头位置在请求数组中的索引。
- 如果未找到,计算当前磁头位置应该插入的位置:index = -index - 1。
- 初始移动方向是增大方向:
- 如果 start <= request[0],表示磁头在最小请求之前,直接移动到最大请求位置。
- 如果 start 在请求数组中间或者右边,先移动到磁道最大位置,再返回到起点,然后移动到start前一个位置。
- 易错:路径记得加上磁道最右到最左距离!
- 返回平均寻道长度
1 | public double CSCAN(int start,int[] request){ |
5.LOOK算法
- SCAN算法的升级,只要磁头移动方向上不再有请求就立即改变磁头的方向
- 初始化:
- sumDistance:总寻道距离,初始为0。
- n:请求数组的长度。
- 对请求数组进行升序排序:Arrays.sort(request);
- 查找当前磁头位置:
- 使用 Arrays.binarySearch(request, start) 查找当前磁头位置在请求数组中的索引。
- 如果未找到,返回一个负数,该负数的绝对值减一即为start 应该插入的位置。
- 计算当前磁头位置应该插入的位置:
index = -index - 1。
- 计算当前磁头位置应该插入的位置:
- 判断初始移动方向:
- 如果 direction 为 true,表示初始移动方向是增大方向。
- 从 index 开始向右遍历请求数组,累加距离。
sumDistance += Math.abs(currentTrack - request[i])
;
- 然后从 index - 1 开始向左遍历请求数组,累加距离。
- 从 index 开始向右遍历请求数组,累加距离。
- 如果 direction 为 false,表示初始移动方向是减小方向。
- 从 index - 1 开始向左遍历请求数组,累加距离。
- 然后从 index 开始向右遍历请求数组,累加距离。
- 如果 direction 为 true,表示初始移动方向是增大方向。
- 返回平均寻道长度
1 | public double LOOK(int start,int[] request,boolean direction){ |
6.C-LOOK算法
- 默认磁头向磁道号增大方向移动
- C-SCAN算法的改进,只要在磁头移动方向上不再有请求,就立即让磁头返回起点
- 初始化
- sumDistance:总寻道距离,初始为0。
- currentTrack:当前磁头所在的磁道号,初始为 start。
- n:请求数组的长度。
- 对请求数组进行升序排序:Arrays.sort(request);。
- 查找当前磁头位置:
- 使用 Arrays.binarySearch(request, currentTrack) 查找当前磁头位置在请求数组中的索引。
- 如果未找到,计算当前磁头位置应该插入的位置:index = -index - 1。
- 初始移动方向是增大方向:
- 从 index 开始向右遍历请求数组,累加距离。
- 然后从 0 开始向右遍历到 index - 1,累加距离。
- 返回平均寻道长度
1 | public double CLOOK(int start,int[] request){ |
If you like my blog, you can approve me by scanning the QR code below.