0%

L28-生磁盘的使用

  • 磁盘的使用和前面 I/O 设备的使用一样,也是包括 CPU 向磁盘控制器的寄存器发送指令、磁盘完成指令后向 CPU 发出中断以及文件视图。

L28 生磁盘的使用

  • 磁盘的使用和前面 I/O 设备的使用一样,也是包括 CPU 向磁盘控制器的寄存器发送指令、磁盘完成指令后向 CPU 发出中断以及文件视图,如下图所示。

磁盘的组成

  • 硬盘中一般会有多个磁盘,这多个磁盘由一根转轴连着,每个磁盘都有上下两个盘面,每个盘面都对应有一个磁头。

    每一个盘面上都有一堆磁道,每一个磁道又可以分为若干个扇区,当选中的磁头落在某一扇区上时,磁头上的电和磁盘扇区上的磁相互作用,磁信号就转变为电信号,该扇区就被使用了。

磁盘的 I/O 过程

  • ★读磁盘的过程是:首先根据 CPU 发送的指令,选择柱面C(确定柱面就相当于确定了磁道)、磁头H(每个磁头都有其对应的盘面)、扇区S和缓存位置(即内存存储位置),然后将选择的磁头移动到指定的磁道上——移动磁头,然后磁盘旋转带动磁道旋转,当磁道旋转至磁头落在所需的扇区上时——旋转磁道,通过磁生电,磁信号转换为电信号,就把扇区中的内容读出,通过 DMA 技术将读出的内容存储到内存中——进行读写

    写磁盘的过程类似,只不过是由电信号转换为磁信号。

最直接的使用磁盘
  • 最直接的使用磁盘就是如前面所述,往控制器中写入柱面C(确定磁道)、磁头H(确定盘面)、扇区S和缓存位置,通过这些参数来使用磁盘。

  • 但是每次访问磁盘都需要传输这么多参数,不够方便,为了方便用户使用磁盘,需要对磁盘的使用进行抽象。

★★★通过盘块号读写磁盘
  • 由于扇区的数量比较小,数目众多在寻址时比较困难,所以操作系统就将相邻的扇区组合在一起,形成一个块,再对块进行整体的操作,这个块就是盘块。

  • 用户只需发送一个盘块号来读写磁盘,而由操作系统的磁盘驱动将盘块号转变为柱面、磁头、扇区参数(CHS),就能找到对应的扇区(这里的”扇区“其实是将几个纵向相邻的“基本扇区”(硬盘最小读写单元的扇区)合并出来的盘块(操作系统针对硬盘读写的最小单元))。

    操作系统除了能方便用户使用硬件以外,还应该能让用户更高效地使用硬件,当我们让用户通过盘块号来使用磁盘时,还应注意到,用户在访问磁盘时,通常都是一次性连续访问几个盘块的,所以应该要能让 block 相邻的盘块可以快速读出

    由下图可以看出,读写磁盘中的数据到内存中时,磁盘访问时间 = 写入控制器时间 + 寻道时间(寻找柱面,亦即寻找磁道时间)+ 旋转时间(寻找扇区时间)+ 传输时间。磁盘访问时间中的大部分就是寻道时间和旋转时间,因此,为了高效访问磁盘,就要减少寻道时间和旋转时间,所以 ,为了让 block 相邻的盘块可以快速读出,就应该让 block 相邻的盘块尽量放在同一个磁道上

    盘块号 Block = C * (Heads*Sectors) + H * (Sectors) + S,在得到了盘块号以后,就可以反推 CHS。

    注意:一个盘块包含纵向相邻的几个扇区,这是因为扇区的数量比较小,数目众多在寻址时比较困难,所以操作系统就将纵向相邻的几个扇区组合在一起,形成一个块,再对块进行整体的操作。

    扇区是硬盘的最小读写单元,大小一般是 512 个字节;而盘块是操作系统针对硬盘读写的最小单元。(盘块 >= 扇区)

  • 到现在,用户根据操作系统访问磁盘就不再是访问磁盘的扇区了,而是访问磁盘的盘块。

★多个进程通过队列使用磁盘

  • 前面所说的通过盘块号来读写磁盘是对磁盘使用的第一层抽象,即用操作系统读写盘块来代替读写扇区,接下来要介绍的是在此基础上的第二层抽象。

    前面所述的操作系统读写磁盘都是针对一个进程来说的,而对多个进程请求读写磁盘的情况,就要用到队列,所以就会存在调度问题,调度的目标是平均访问延迟时间小,寻道时间是主要的矛盾

FCFS磁盘调度算法
  • FCFS磁盘调度算法和前面进程调度的FCFS调度算法概念相同,见下图。
SSTF磁盘调度算法
  • 从上图中可以看到,FCFS磁盘调度算法的问题是磁头在移动到下一磁道的过程中,即使经过了后面要请求访问的磁道,当前也并不去访问,而只是根据请求队列一个一个地访问,所以磁头在“长途奔袭”,耗时很久。

    那么一个自然而然的想法就是,让磁头在移动的过程中,顺便把后面要请求访问的磁道也先访问了,这样就可以减少磁头来来回回“长途奔袭”的次数,即演变成,磁头优先访问离当前磁道最近的下一个磁道,这种调度算法称为 SSTF 磁盘调度算法(Shortest-Seek-Time First,短寻道优先算法)

    但是这种调度算法存在“饥饿”问题,因为进程在访问磁盘时,大部分的访问还是集中在盘面中心部分的磁道上,如果磁头还在盘面中心部分的磁道上进行访问时,又来了一些访问磁盘的请求,而且这些请求多是在盘面中心部分,那就会形成磁头一直在盘面中心部分访问磁道,而不会访问盘面边缘部分的磁道的现象,就会存在饥饿。

SCAN磁盘调度算法
  • 针对 SSTF 算法存在的问题,为了能顾及到访问盘面边缘部分的磁道的请求,又为了能让磁头不要来来回回“长途奔波”,所以提出了 SCAN 磁盘调度算法,SCAN 磁盘调度算法 = SSTF 磁盘调度算法 + 中途不回折
★C-SCAN磁盘调度算法 - 电梯算法
  • C-SCAN 磁盘调度算法是对 SCAN 磁盘调度算法的进一步改进,C-SCAN 磁盘调度算法 = SCAN 磁盘调度算法 + 直接移动到另一端(例如直接从0到199) ,所以访问盘面内端和外端两端的磁道的请求可以很快处理,而且磁头的复位是很快的。

★★★生磁盘使用的总结

  • 使用生磁盘的总结:

    • 首先磁盘在完成上一个读写任务后,就会向 CPU 发出中断,请求中断处理,来唤醒之前因请求访问磁盘而睡眠的进程;
    • 然后磁盘从请求访问磁盘的进程请求队列中取出下一个要访问的盘块号,而这个队列是根据 C-SCAN 磁盘调度算法(电梯算法)来进行排列的(在将进程访问磁盘的请求插入到队列中时,就会根据电梯算法来进行插入,同时该进程睡眠);
    • 在得到了下一个要访问的盘块号后,磁盘就会请求中断处理(do_hd_request),请求 CPU 根据根据盘块号计算 CHS,即得到了柱面、磁头和扇区的参数;
    • 然后 CPU 将得到的 CHS 参数通过 out 指令发送给磁盘控制器,此时 CPU 就去执行别的工作了,而磁盘控制器进行磁盘的访问,并将访问得到的数据通过 DMA 存储到内存中;
    • 在将访问得到的数据通过 DMA 存储到内存中后,磁盘就又向 CPU 发出中断,然后循环上述步骤。
---------------The End---------------