文章目录
0 回顾
- 还是从硬件开始
- 从磁盘开始,怎么让磁盘用起来,再转起来
- 其实和控制之前的外设一样,核心是out再加上中断处理
1 磁盘
- 磁盘的基本单位是扇区
- 磁盘的一个扇区是512字节
- 扇区的大小是传输时间和碎片浪费的折衷
1.1 使用磁盘
- 读/写一个字节,具体的操作如下:
- 首先将磁头移动到指定的磁道上
- 然后磁道开始旋转
- 转到相应的扇区以后,再一转,磁生电电生磁
- 磁生电的时候,磁信号就变成电信号,然后就读回去了,也就是读到内存的缓冲区当中
- 读到内存的缓冲区后 ,再将这个内存缓冲区修改一个字节,然后再到里面转,再电生磁,把这个字节写进去
- 核心就是移动磁头移动到磁道上,然后转动磁道移动到扇区上,然后一边旋转一边磁生电电生磁和内存缓冲区进行数据的交互,是读了还是写了都一样
综上,磁盘/O过程:控制器→寻道→旋转→传输!
怎么使用磁盘?就是移动磁头,旋转磁盘,进行读写,就是这三步,所以只要告诉计算机/磁盘控制器这几个数怎么移动磁头,怎么旋转,这样,磁盘驱动器就会自己工作,核心就是告诉磁盘控制器这几个参数
1.2 最直接的使用磁盘
- 柱面: 就是刚刚移动的磁道(将磁头移动到磁道上)(现在不是一张盘,现在是一堆盘,所以现在就是一堆磁道形成一个柱面,知道柱面后,磁壁就会移动到相应的柱面上),
cyl
- 磁头: 旋转到这个柱面了,那到底是在第一个盘面读写还是其他几个呢?这就要根据磁头来定,
head
- 扇区: 到底读写这个盘面的哪个扇区
sec
- 所以传递了这三个值,磁盘就知道该怎么移动磁壁,怎么让哪个磁头上电,怎么旋转磁盘
- 再告诉缓冲区后(告诉内存的位置),接下来就可以利用总线倒用技术DMA进行倒用总线,这样的话就可以将磁盘扇区上的数据放到内存上,或者将内存的数据写到扇区上,这样就完事了,具体来说,只要传递这几个值就可以读写磁盘,写到磁盘控制器上,用out指令
void do hd request(void)
{··.hd out(dev,nsect,sec,head,cyl,WIN WRITE,...)
port write(HD DATA,CURRENT->buffer,256);}
void hd out(drive,nsect,sec,head,cyl,cmd...)
{
port=HD_DATA;//数据寄存器端口(0x1f0)
outb_p(nsect,++port);outb_p(sect,++port);
outb p(cyl,++port);outb_port(cyl>>8,++port);
outb_p(0xAOI(drive<<4)head,++port);
outb p(cmd,++port);}
- 可以看出,最后就是一堆out指令
- 就是通过这些out指令,把磁头,柱面,扇区都写到了某些端口上
- 并且这些柱面磁头扇区还要转变为他认的格式,所以要左移右移进行拼接,这些都是细节
SSD本来就不是磁盘(uh-oh),实际上它是一种闪存( f l a s h flash flash),操作当然不一样。
1.3 通过盘块号读写磁盘
- 上面那种还是太麻烦了,因为要知道很多信息,现在想直接知道磁盘号就能完成类似的工作该怎么做?
- 可以发个盘块号,总比发磁头扇区柱面这三个参数要容易的多
- 用户根据盘块号来读写磁盘
- 磁盘驱动会负责将盘块号来计算出那三个参数,柱面磁头扇区(后面简称CHS)
- 这是这一层抽象的核心
- CHS是一个三维编址(参考柱面坐标系)
- 而盘块号是一维编址,所以要明白一维到三维的这个换算编址
- 现在要求,连续的盘块号可以快速读出(就是在浪费时间的地方少浪费时间)
- 主要是移动磁壁时间花费多,这个时间又称为寻道时间,寻找哪个磁道,寻找哪个柱面,最核心的就放在寻道时间上
- 现在我们希望相邻盘块号的盘块应该尽量放在同一个磁道,这样才能让连续盘块进行读写的时候,尽量少花费时间,少花费时间就是少寻道
- 磁头数不一定等于盘数,而是等于盘面数,一个盘可能两面都有磁性物质的
- Sectors: 总扇区数,Heads: 总磁头数;C: 目标柱面,H: 目标磁头,S: 目标扇区
- 上方的公式当中,第一项是一个完整的柱面包含的扇区数,第二项是前H个磁头包含的扇区数,最后加上 S S S个扇区就是 b l o c k block block了
- 所以说 b l o c k block block % \% % s e c t o r s = S sectors = S sectors=S,因为前面的 s e c t o r s sectors sectors都有公因数,所以直接消掉,只剩下一个 S S S了,这样就可以通过 b l o c k block block反推回 C H S CHS CHS了
- 由一个磁道形成的柱面从上到下编号结束了,到下一个磁道开始从上到下的编号,就能理解了。这里理解为每个磁道上的扇区数量是一样的
- 磁盘读写的单位是扇区
- 现在用空间的大小来换时间
- 读写的单位从一个空间换成盘块
- 用空间的浪费换区时间效率,所以读写磁盘的基本单位从扇区变为盘块(几个连续的扇区),也就是磁盘
- 得到连续的扇区,就能得到CHS,这些扇区有了,再通过out发给磁盘控制器,进行计算
1.4 输出block
- 现在使用磁盘可以通过盘块号使用,block
- 用下方的公式,就能算出CHS
- linux0.11的盘块是2个扇区
- 盘块越大读写效率越高
1.5 多进程使用盘块
- 多个进程的话必须形成请求队列
- 到底应该先给谁呢?这就要进行折中和调度
- 磁盘驱动从队列当中取出来,算出CHS
- 这里仍然是生磁盘,即从盘块号来使用
- 熟磁盘是使用文件的
多个磁盘访问请求出现在请求队列怎么办?
调度的目标是仕么?调度时主要考察什么?
- 给调度算法,仍然从FCFS开始
- 对磁盘来说,时间是最核心的因素,寻道时间又是最主要的大头
- FCFS先来先服务,从中发现问题,在一步步改进
1.6 FCFS磁盘调度算法
- 每个进程访问磁盘,由程序决定
- 那些数字代表柱面
1.7 SSTF短寻道优先磁盘调度
- 在移动过程中把经过的请求处理了
- 位于中间的比较多,总是会在中间晃荡,磁头总在中间移动
- 远处请求划不过去,存在饥饿
1.8 SCAN扫描磁盘调度
- 扫过去再扫回来
- 既公平,又移动比较小
1.9 C-SCAN磁盘调度(电梯算法)
- 就是这个电梯只有一个方向,走到头了立刻复位,复位过程不带人
- 多进程通过电梯算法将自己的的请求放在队列当中
1.10 多进程使用磁盘
- 注解如下if当中的条件
- 当temp->next小于temp的时候相当于进行了折回
- 第一种是上楼的过程中处理,第二种是折回来从头处理
- 猜测队列第2种情况是req<tmp<next情况,然后让tmp先向左扫req再向右扫next,不知道对不对
- 就是反向复位的时候如果req<next,就先复位到req再正向扫描
- 第一个条件,是看req是不是能在上楼过程中被处理,后面那个条件是将req放在下楼过程中处理