生磁盘

认识磁盘

磁盘的基本工作过程:

  • 磁头移动,找柱面C

  • 寻找磁道,对应磁头上电H

  • 旋转磁盘,选择扇区S

  • 开始读写

扇区是磁盘读写的基本单位。

因此只要由柱面、磁头、扇区、缓存位置这几个信息,就可以定位磁盘里的内容了。

有了这几个值,就可以使用DMA技术,传数据了。DMA,直接存储器访问,总线盗用技术,偷摸着使用总线。

最直接的使用就是这么搞。参数很多。

直接使用的代码在linux/kernel/blk_drv

/* 直接使用生磁盘 */
void do_hd_request(void)
{
    hd_out(dev, nsect, sec, head, cyl, WRITE);
}

另一个想法是能不能简单一点,像地址一样,一个参数,剩下的系统驱动搞定。这是第一层封装。使用盘块号来读写硬盘,一个盘块号包含了几个扇区。

第一层抽象:通过盘块号读写

第一层抽象。

磁盘是三维编址,CHS,制造成这样了。对于程序来说,按照块来,只使用一个block号,磁盘驱动算出来CHS三个参数。

这就涉及到一个编址问题,要去考虑磁盘物理结构和工作效率问题。我们希望block相邻的盘块可以快速读出。

磁盘访问时间=写入控制器时间+寻道时间+旋转时间+传输时间

寻道时间8~12ms

旋转时间7200r/min,半圈4ms

传输时间50M/s,

编号的时候先在同一磁道内编,然后同一柱面上,由上向下编。

硬件最终读写的扇区,对于磁盘来讲,磁头移动的越少。读写效率越高,所以牺牲一点空间,换更短的时间。

使用盘块号就隐藏了许多细节。

驱动程序里包含了对生磁盘的使用,由盘块号计算CHS参数。

可以在程序看出Linux0.11的盘块为2个扇区。

第二层抽象:多进程队列使用磁盘

多个进程同时使用磁盘,需要排队等待,这时候就又有了个先后的问题。

排好队该先挑哪一个进程来读取呢?调度问题。

这又是个算法的问题,调度的目标是如何让磁盘的评价访问时间最小。

最公平的是FCFS先来先服务,这种情况下磁头臂在不断的长途运动,可以将中间路过的页处理了。基于这个方法出现了短寻道时间优先(SSTF)。

这种情况下,磁头总是在中间一段移动,对读写频繁的程序有利。在远处的请求就无法照顾,所以SSTF存在饥饿问题。

SSTF+中途不折返,即SCAN算法。这种情况还是照顾了中间,再改进一下。

SCAN+直接移动到另一端,C-SCAN磁盘调度,即电梯算法。每个请求都有机会处理,相当公平。

生磁盘使用

  • 进程“得到盘块号”,算出扇区号

  • 用扇区号make req,用电梯算法add_request

  • 进程sleep_on,进程间合作等待

  • 磁盘中断处理

事实上,进程操作的是文件,文件到盘块号还要走一段路,就是接下来的内容。

最后更新于