Mengzelev's Blog

OSTEP阅读笔记-持久化部分

Word count: 1,609 / Reading time: 6 min
2019/06/21 Share

Ch36 IO设备

典型设备协议

设备的两个重要组成部分:硬件接口+内部结构

OS通过读写状态、命令和数据寄存器来控制设备行为

协议模型

1
2
3
4
5
6
7
while(STATUS == BUSY);
//wait until device is not busy(polling)
write data to DATA reg;
write cmd to cmd reg;
(Doing so starts the device and executes the cmd)
while(STATUS == BUSY);
//wait until device is done with your request

缺陷:轮询浪费时间——用中断减少CPU浪费(概括一下:等待设备的时候去做别的事情)

使用中断还是轮询取决于设备的速度

DMA

要传送数据的时候,OS告诉DMA数据在哪里、送多少、要送给谁,然后OS就可以去干别的事了,数据拷贝全部由DMA来完成

OS与设备的交互

明确的I/O指令

古代方法
e.g. x86in,out指令
PA你都写过了
都是特权指令,只有OS可以使用

内存映射

现代方法
但古代方法没有被抛弃

设备驱动

by传统艺能:抽象
设备驱动:OS中的某一块(piece)知道设备的工作细节的软件,封装了所有与设备的交互行为(原话:a piece of software in the OS must know in detail how a device works)
但这样会使设备损失特殊功能(e.g SCSI有比ATA和IDE更丰富的error handling机制)
OS里70%的代码都是设备驱动程序,而且因为设备驱动主要都是野鸡程序猿(相对于内核代码)写的,所以是贡献内核bug的中坚力量

Ch37 硬盘驱动

虽然现代os会一次性往硬盘写很多数据,但是硬盘只保证一个sector(512字节)的写是原子的(要么写了要么没写)

物理构造

盘片(platter)的两个面称为盘面(surface),盘片装在转轴(spindle)上。数据按磁道(track)排列在盘片上,由磁头(disk head)读写。每个盘面都有一个磁头(disk head)。磁头长在磁臂(disk arm)上
RPM(rotation per minute)

缓存(track buffer)

写判定

  • 写回(write back): 把数据放入磁盘缓冲就算写完
  • 直写(write through): 把数据写入磁盘后才算写完

下面都是磁盘读写调度我不看了啦

Ch38 RAIDs

Redundant Arrays of Inexpensive Disks廉价磁盘冗余阵列
RAID其实是一个firmware(编程硬件),有自己的处理器、存储和磁盘

###评价标准
performance, capacity, reliability.
其中performance有两个判定尺度:single-request latency(单操作延迟), steady-state throughput(稳态吞吐量, the total bandwidth of many concurrent requests)

故障模型(Fault Model)

fail-stop

磁盘只有两个状态:wording & failed(永远没有了),不考虑坏了半块这样的情况

RAID Level 0: Striping(串列)

毫无冗余,虚假的RAID

capacity: perfect
reliability: any disk failure will lead to data loss
performance: excellent

【此处省略懒得截图的截图】
stripe: 排在同一行的blocks
chunk size(组块大小): 连续分布在同一块磁盘上的数据大小
chunk size对RAID的performance影响最大
小的chunk size能提高连续读的并发性,但是延长了把block分配到不同磁盘的时间
大的chunk size只有在读大文件时才能有较好的并发性,但缩短了分配时间
chunk size的选择依赖于workload

workload有两种:sequential和random

RAID Level 1: Mirroring

图上那个又叫RAID-10

读:随机选一个
写:两份都要写(并发)

  • capacity: N块磁盘,容量N/2
  • reliability: 可以忍受单块磁盘爆炸(只要不是同一块磁盘的两个备份同时爆炸)
  • performance:
    • 读延迟:速度同读单块磁盘
    • 写延迟:同时写两份(并发),与同时写单块相同。但写时间由两块中时间长的决定,因此比写单块会慢一丢丢
    • 连续读:同随机写
    • 连续写:最大带宽$(\frac{N}{2}\cdot S)$,峰值带宽的一半
    • 随机读:满带宽$N\cdot R$ MB/s
    • 随机写:一半

多块磁盘的一致性维护

刚决定写一块磁盘,另一块磁盘写不写还没确定,就断电了,这时另一块磁盘完全没被写,导致两块磁盘数据不一致。也就是说希望镜像的两块盘的写操作是原子的。
解决:write-ahead log
大多数磁盘都带有电池供电的小型非易失性RAM

RAID Level 4: Saving Space With Parity

用时间(performance)换空间(capacity)

给每个stripe加了一个parity check block(XOR)
当一块盘坏掉时,我们需要读同一个stripe中其他所有盘的数据才能恢复出这块盘的数据

  • capacity: $N-1$
  • reliability: 能容忍每个stripe中有一块磁盘爆炸
  • performance
    • 连续读:只有校验盘没有被占用,$(N-1)\cdot S$ MB/s
    • 连续写:full-stripe write很高效,因为写完一个stripe正好能写校验盘,$(N-1)\cdot S$ MB/s
    • 随机读:除了校验盘,$(N-1)\cdot S$ MB/s
    • 随机写:当修改了一块盘中的数据时,需要同时修改校验盘,这里有两种方法。一是additive parity,把同一个stripe中的块的数据全部读出来再算一遍校验位,然后并发地写入校验盘和数据盘,这种做法在RAID块比较多的时候会很慢;另一种是subtractive parity,从检验位中把原来的数据减去再加上新的数据,这种方法的瓶颈在于校验盘不能并发读写,带宽只有$R/2$ MB/s,即使加磁盘也不会加快。
    • 读延迟:同读单块磁盘
    • 写延迟:写单块时需要进行两次读和写(subtractive parity),但读写都可以并发,因此写延迟为写单块磁盘的两倍(速度是一半)

RAID Level 5: Rotating Parity

为了消除RAID-4校验盘的性能瓶颈

三围基本和RAID-4相同
随机读的performance会好一些,因为所有的磁盘都被占用了
随机写性能大大提升,因为写操作之间可以并发了。当有较大的随机写操作序列时,可以保证每块磁盘都能并发工作,但依然有2读2写,带宽是$\frac{N}{4}\cdot R$ MB/s.
在市场上已经基本取代了RAID-4

Summary

一张表格概括本章精髓

方案选择取决于实际使用,对reliability、顺序或随机读写的不同需求

CATALOG
  1. 1. Ch36 IO设备
    1. 1.1. 典型设备协议
      1. 1.1.1. DMA
    2. 1.2. OS与设备的交互
      1. 1.2.1. 明确的I/O指令
      2. 1.2.2. 内存映射
    3. 1.3. 设备驱动
  2. 2. Ch37 硬盘驱动
    1. 2.1. 物理构造
  3. 3. Ch38 RAIDs
    1. 3.1. 故障模型(Fault Model)
      1. 3.1.1. fail-stop
    2. 3.2. RAID Level 0: Striping(串列)
    3. 3.3. RAID Level 1: Mirroring
      1. 3.3.1. 多块磁盘的一致性维护
    4. 3.4. RAID Level 4: Saving Space With Parity
    5. 3.5. RAID Level 5: Rotating Parity
    6. 3.6. Summary