生磁盘
认识磁盘
磁盘的基本工作过程:
磁头移动,找柱面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,进程间合作等待
磁盘中断处理
事实上,进程操作的是文件,文件到盘块号还要走一段路,就是接下来的内容。
最后更新于