1本章要解决的问题

如何在磁盘上存储和访问数据?现代硬盘怎样存储数据?接口是什么?数据在盘上怎样布局、怎样被访问?磁盘调度如何提升性能?

How do modern hard-disk drives store data? What is the interface? How is the data actually laid out and accessed? How does disk scheduling improve performance?

上一章讲了操作系统和一般 I/O 设备打交道的通用机制(轮询、中断、DMA、驱动)。这一章专门研究其中最重要的一种设备:硬盘驱动器(hard disk drive, HDD)。几十年来它一直是持久化存储的主力,后面的文件系统(FFS、日志、LFS……)几乎每一个设计决策都建立在"磁盘怎样工作"的认识之上。

本章的核心收获只有一句话,却贯穿整个持久化部分:一次磁盘 I/O 的时间 = 寻道 + 旋转 + 传输,前两项是机械运动,慢得可怕;所以顺序访问比随机访问快几百倍,而磁盘调度就是想办法少做机械运动。

2核心概念速览

扇区数组(array of sectors)

磁盘对外就是 0 到 n−1 编号的 512 字节扇区;只有单个扇区的写是原子的。

盘片 · 表面 · 磁道

盘片两面都是表面;每个表面上有成千上万条同心圆磁道,每条磁道上排着扇区。

寻道(seek)

磁臂把磁头移到目标磁道:加速、滑行、减速、稳定,毫秒级,最贵的操作之一。

旋转延迟(rotational delay)

磁头到位后等目标扇区转过来。平均半圈:15000 RPM 时是 2ms。

传输(transfer)

扇区从磁头下经过时真正读写数据。对小请求来说它只占很少时间。

TI/O 与 RI/O

TI/O = Tseek + Trotation + Ttransfer;RI/O = 传输大小 / TI/O。

磁盘调度(disk scheduling)

磁盘请求的"作业长度"可以估算,所以能做近似 SJF:SSTF、SCAN/C-SCAN、SPTF。

磁道偏斜 · 缓存

track skew 让跨磁道顺序读不错过扇区;磁道缓冲(track buffer)缓存整条磁道,write-back 更快但有风险。

3接口:一个扇区数组

现代磁盘的基本接口很简单:驱动器由大量扇区(sector)组成,每个 512 字节,可读可写。在有 n 个扇区的磁盘上,扇区编号从 0 到 n−1,这就是驱动器的地址空间。多扇区操作当然可以(很多文件系统一次读写 4KB 甚至更多),但厂商只保证单个 512 字节的写是原子的:要么完整写入,要么完全没写。如果写 4KB 的过程中突然断电,可能只有其中一部分扇区写上了,这叫撕裂写(torn write)。

磁盘 = 扇区数组(每格 512 字节) 写一个 4KB 块(扇区 8–15)时断电: 前 5 个扇区已是新数据(N),后 3 个还是旧数据(O)——"撕裂写"。每个扇区内部不会出现半新半旧。
磁盘接口:扇区编号 0…n−1;只有单扇区写是原子的

此外还有一些接口里没写、但大家都默认的"不成文的约定"(unwritten contract):地址空间里相邻的两个块,访问起来比相距很远的两个块快;连续访问一段块(顺序读写)是最快的方式,通常比任何随机访问模式快得多。读完本章你会明白这些约定从何而来。

4基本几何结构

盘片(platter)是一张坚硬的圆盘(比如铝),表面镀一层很薄的磁性层,通过改变磁性来持久存储比特,断电后数据依然保留。一个磁盘可以有一张或多张盘片,每张盘片有两面,每一面叫一个表面(surface)。所有盘片固定在主轴(spindle)上,电机带动主轴以恒定速率旋转,速率用 RPM(每分钟转数)衡量,常见 7200–15000 RPM。10000 RPM 的磁盘转一圈大约 6ms。

每个表面上的数据按同心圆组织,一圈叫一条磁道(track);一个表面有成千上万条磁道,一根头发丝的宽度里就能挤下几百条。读写靠磁头(disk head)完成,每个表面一个;所有磁头装在同一个磁臂(disk arm)上,磁臂在表面上移动,把磁头定位到想要的磁道。

侧视:多张盘片共用一根主轴 主轴 spindle 盘片 platter ×3 每片上下两个表面 surface 磁头 head:每个表面一个 全部装在同一个磁臂 arm 上,一起移动 俯视:一个表面 橙色一圈 = 一条磁道 track 逆时针旋转
盘片、表面、主轴、磁道、磁头、磁臂

5一个简单的磁盘:单磁道与旋转延迟

从最简单的模型开始,一次加一条磁道。假设磁盘只有一条磁道,12 个扇区,编号 0–11,每个 512 字节(Figure 37.1)。加上磁头和磁臂(Figure 37.2),磁头此刻停在扇区 6 上方,盘片逆时针旋转——所以扇区按 6、7、8……11、0、1 的顺序依次经过磁头。

Figure 37.1 / 37.2:只有一条磁道的磁盘 + 磁头(停在扇区 6)。橙色是请求的扇区 0

现在来了一个读扇区 0 的请求。在单磁道磁盘上,驱动器什么也不用移动,只需等待扇区 0 转到磁头下面。这段等待在现代磁盘里经常发生,而且占 I/O 服务时间的很大比重,因此专门叫旋转延迟(rotational delay)。如果转一整圈要 R,从 6 等到 0 大约要 R/2。最坏的请求是扇区 5:刚刚错过,几乎要等一整圈。

6多磁道:寻道

再现实一点:三条磁道(Figure 37.3 左)。外道是扇区 0–11,中道 12–23,内道 24–35;磁头现在在最内道。来了一个读扇区 11 的请求,驱动器必须先把磁臂移到正确的磁道(最外道),这叫寻道(seek)。寻道和旋转一起,是磁盘最昂贵的操作。

Figure 37.3 左:磁头在内道,请求扇区 11
Figure 37.3 右:寻道期间盘片转过约 3 个扇区,9 正要经过磁头,再等一小段就到 11

寻道本身分好几个阶段:加速(磁臂开始移动)→ 滑行(全速移动)→ 减速 → 稳定(settling)——磁头必须精确地停在正确的磁道上(差一点都不行),稳定时间往往就要 0.5–2ms。

时间 磁臂速度 加速滑行(全速)减速稳定 settle 0.5–2ms:反复微调直到确认在正确磁道上
一次寻道的速度-时间曲线(示意)

寻道完成后,磁头已经在正确磁道上,但盘片在这段时间里也在转(Figure 37.3 右,约转过 3 个扇区),此时扇区 9 正要经过磁头,只需再忍受一小段旋转延迟。当扇区 11 经过磁头时,进入最后一个阶段:传输(transfer),数据被读出或写入。完整的 I/O 时间由此得出:先寻道,再等旋转,最后传输。

7一些其他细节:偏斜、多区与缓存

磁道偏斜(track skew)

很多驱动器会让相邻磁道的扇区编号错开一些,保证跨磁道的顺序读也能顺畅进行。原因是:从一条磁道切换到相邻磁道时,磁头需要时间重新定位(即使只移动一道)。如果没有偏斜,磁头刚到下一条磁道,想要的下一个块已经从它下面转过去了,只能再等将近一整圈。

无偏斜:读完 11 再寻道到中道,12 已经转过去了
Figure 37.4:偏斜 2 个扇区,寻道完成时 12 恰好快要转到

在后面的模拟器里载入 10,11,12,13 这组请求,对比偏斜 0 和偏斜 2:总时间从 585 降到 285。

多区(multi-zoned)

外圈磁道比内圈长,自然能放更多扇区。多区磁盘把表面分成若干区(zone),一个区是一组连续的磁道;同一区内每条磁道扇区数相同,外侧的区每道扇区更多。由于转速恒定,外圈每秒经过磁头的扇区更多,所以外圈的顺序带宽更高。

外区:每道 24 个扇区(示意) 中区:每道 16 个扇区 内区:每道 10 个扇区 转速相同 → 外区每转一圈读到的数据更多
多区磁盘:同一区内每道扇区数相同,越往外越多

磁道缓冲:write-back 与 write-through

现代驱动器都有一块缓存(cache),历史原因也叫磁道缓冲(track buffer),通常 8 或 16MB。读一个扇区时,驱动器可能顺手把整条磁道都读进缓存,之后对同一磁道的请求就能立刻返回。写的时候驱动器有个选择:数据放进缓存就报告"写完了",叫 write-back 缓存(又叫 immediate reporting);真正写到盘面上才报告,叫 write-through。write-back 让磁盘"看起来"更快,但有风险:如果文件系统或应用依赖写入顺序来保证正确性(第 42 章的日志就是这样),write-back 可能打乱顺序、断电时造成问题。

write-through 主机 盘内缓存 盘面 落盘后才确认:慢但安全 write-back 主机 盘内缓存 盘面(稍后) 进缓存就确认:快,断电可能丢、可能乱序
两种写缓存策略

8I/O 时间:算一算

化学课上"让单位互相约掉,答案自己冒出来"的方法叫量纲分析(dimensional analysis),在系统分析里同样好用。例 1:10000 RPM 的磁盘转一圈多少毫秒?把想要的单位写在左边,再把已知条件依次乘上,让单位约掉:

Time (ms)1 Rotation = 1 minute10,000 Rot. · 60 seconds1 minute · 1000 ms1 second = 60,000 ms10,000 Rot. = 6 ms / 圈

例 2:传输速率 100MB/s,传 512KB 要多少毫秒?

Time (ms)1 Request = 512 KB1 Request · 1 MB1024 KB · 1 second100 MB · 1000 ms1 second = 5 ms / 请求

有了磁盘的抽象模型,就可以用一点数学来分析性能。I/O 时间是三部分之和:

T_I/O = T_seek + T_rotation + T_transfer          (37.1)
R_I/O = Size_Transfer / T_I/O                      (37.2)

比较驱动器时,I/O 速率 RI/O 更好用。原书拿两块 Seagate 磁盘做对比:高性能 SCSI 盘 Cheetah 15K.5 和面向容量的 SATA 盘 Barracuda(Figure 37.5):

Cheetah 15K.5Barracuda
容量300 GB1 TB
转速15,000 RPM7,200 RPM
平均寻道4 ms9 ms
最大传输率125 MB/s105 MB/s
盘片数44
缓存16 MB16/32 MB
接口SCSISATA

这两块盘正好代表磁盘市场的两极:"高性能"市场追求转得快、寻道短、传得快;"容量"市场最在乎每字节的成本,盘慢一些,但尽量塞下更多比特。考虑两种负载:随机负载(random)向磁盘随机位置发出小的(如 4KB)读请求,数据库等应用很常见;顺序负载(sequential)连续读大量扇区。用下面的计算器复现原书的计算(参数可改):

计算器

随机 vs 顺序:两块磁盘的 TI/O 与 RI/O

改转速、平均寻道、传输率、请求大小,看三部分时间各占多少、I/O 速率差多少倍。约定 1MB = 1024KB;平均旋转延迟取半圈。

Cheetah 15K.5

Barracuda

负载

逐项看原书的 Cheetah 随机负载:平均寻道直接取厂商给的 4ms(全程寻道大约要 2–3 倍长);15000 RPM = 250 转/秒,一圈 4ms,平均等半圈 2ms;4KB 以 125MB/s 传输只要约 30µs(1ms 可是 1000µs!),小到可以忽略。于是 TI/O ≈ 6ms,RI/O ≈ 4KB / 6ms ≈ 0.66MB/s。Barracuda 的 TI/O ≈ 13.2ms,慢一倍多,RI/O ≈ 0.31MB/s。顺序负载假设只寻道、旋转一次,然后传 100MB:TI/O 约为 800ms 和 950ms,I/O 速率几乎就是峰值传输率 125 和 105MB/s(Figure 37.6):

CheetahBarracuda
RI/O 随机0.66 MB/s0.31 MB/s
RI/O 顺序125 MB/s105 MB/s

说明:原书数字是四舍五入的近似(把 T 取成约 6ms、13ms,把 4KB 当成约 0.004MB)。计算器按 1MB = 1024KB 精确计算,得到 0.65 和 0.30MB/s、顺序 124 和 104MB/s,结论完全一样。

这张表说明了两件事。第一,也是最重要的:随机和顺序负载之间有巨大的性能差距,Cheetah 约 200 倍,Barracuda 超过 300 倍。由此得到计算史上最显而易见的设计建议:

顺序地使用磁盘(Use disks sequentially)。只要可能,就按顺序传输数据;做不到顺序,至少要用大块传输,越大越好。如果 I/O 是零零碎碎的随机小块,性能会急剧下降,用户会受苦,你也会受苦——因为你知道这都是你那些随手的随机 I/O 造成的。

第二点更微妙:"高性能"盘和"容量"盘的性能差距也很大。所以人们愿意为前者付高价,而对后者则尽量买便宜的。

9旁注:为什么平均寻道是全程的 1/3

书和论文里常说"平均寻道时间约为全程寻道的三分之一"。这来自平均寻道距离的计算(不是时间)。把磁道编号为 0 到 N,任意两道 x、y 之间的寻道距离是 |x − y|。所有可能寻道的距离之和用积分近似:

∫₀ᴺ ∫₀ᴺ |x − y| dy dx
内层拆开绝对值:∫₀ˣ (x − y) dy + ∫ₓᴺ (y − x) dy = x² − Nx + N²/2
外层:∫₀ᴺ (x² − Nx + N²/2) dx = N³/3 − N³/2 + N³/2 = N³/3
除以寻道总数 N²:平均距离 = N/3
小实验

用穷举验证 N/3

枚举所有 (x, y) 磁道对,画出寻道距离的分布(越短的距离出现越多),并比较真实平均值与 N/3。
30

10磁盘调度

I/O 代价这么高,操作系统历来会插手决定磁盘请求的顺序。给定一组 I/O 请求,磁盘调度程序(disk scheduler)检查它们并决定下一个服务哪个。和进程调度不同,进程的运行时间通常不可知,而磁盘请求要花多久却能估算得相当准:估计寻道和可能的旋转延迟即可。于是磁盘调度器可以贪心地先做最短的那个——遵循 SJF(最短作业优先)的原则。

SSTF:最短寻道时间优先

SSTF(shortest-seek-time-first,也叫 SSF)按磁道排序请求,先服务最近磁道上的请求。原书的例子(Figure 37.7):磁头在内道,有扇区 21(中道)和 2(外道)两个请求,SSTF 先发 21,完成后再发 2。

Figure 37.7:SSTF 调度请求 21 和 2

SSTF 不是万能的。第一,操作系统看不到驱动器的几何结构,只看到一个块数组。这好解决:OS 可以改用最近块优先(nearest-block-first, NBF),下一个服务块地址最近的请求。第二个问题更根本:饥饿(starvation)。如果磁头所在的内道源源不断地来请求,纯 SSTF 会完全忽略其他磁道上的请求。

如何处理磁盘饥饿?怎样实现类似 SSTF 的调度,同时避免饥饿?

How can we implement SSTF-like scheduling but avoid starvation?

电梯算法:SCAN 与 C-SCAN

答案早就有了。SCAN 让磁头在磁盘上来回扫,按磁道顺序服务请求。从外到内(或从内到外)扫一遍叫一个扫描(sweep)。如果某个请求所在的磁道这一趟已经扫过了,它不会被立即处理,而是排到下一趟(反方向)。变种有:

SCAN:来回扫 C-SCAN:单向扫,到头跳回 外道 ← 磁道 → 内道外道 ← 磁道 → 内道 中间道:等间隔经过 最外道:间隔两倍长 虚线:快速回到外道 每条磁道都等间隔经过 时间 ↓
磁头位置随时间的轨迹:SCAN 偏爱中间磁道,C-SCAN 对所有磁道一视同仁

SCAN 也叫电梯算法(elevator algorithm),因为它像电梯一样要么向上要么向下,而不是看哪层近就去哪层。想象你从 10 楼下到 1 楼,有人在 3 楼进来按了 4,电梯却因为 4 楼"更近"而掉头上去——多气人!电梯算法在现实中避免了打架,在磁盘上则避免了饥饿。

可惜 SCAN 及其变种(甚至 SSTF)都没有尽可能地贴近 SJF:它们忽略了旋转。

如何计入磁盘旋转的开销?怎样实现同时考虑寻道和旋转、更接近 SJF 的算法?

How can we implement an algorithm that more closely approximates SJF by taking both seek and rotation into account?

SPTF:最短定位时间优先

SPTF(shortest positioning time first,也叫 SATF, shortest access time first)就是答案。看原书的例子(Figure 37.8):磁头在内道扇区 30 上方,下一个该服务中道的 16,还是外道的 8?

Figure 37.8:SSTF 有时不够好

答案是"看情况"(it depends)。取决于寻道和旋转的相对快慢:如果寻道比旋转慢得多,SSTF 及其变种就够了;但如果寻道比旋转快不少,那就应该多寻一段道去服务外道的 8,而不是就近去中道服务 16——16 刚刚转过磁头,得等几乎一整圈。在下面的模拟器里用"原书 Figure 37.8"两个预设按钮对比:寻道速率 S=4 时 SPTF 先做 8,总时间 315;SSTF 先做 16,总时间 435。把 S 改成 1,两者都会先做 16。

几乎任何问题都可以用"看情况"回答,就像作者的同事 Miron Livny 常说的。但请谨慎使用:回答太多次"看情况",人们就不再问你问题了。比如有人问"去吃午饭吗?"你答:"看情况,你也去吗?"更重要的是知道为什么要看情况、看什么情况。

在现代驱动器上,寻道和旋转大致相当(当然取决于具体请求),所以 SPTF 有用、能提升性能。但它在 OS 里更难实现:OS 通常不知道磁道边界在哪,也不知道磁头此刻转到了哪个角度。所以 SPTF 通常在驱动器内部实现。

其他调度问题

11模拟器:仿 disk.py 看寻道、旋转与传输

下面的模拟器复现了原书作业工具 disk.py 的模型:3 条磁道(外道 0–11、中道 12–23、内道 24–35),每道 12 个扇区、每扇区 30°,磁道间距 40 个距离单位。默认寻道速率 -S 1(每时间单位移动 1 个距离单位,所以换一道要 40)、旋转速率 -R 1(每时间单位转 1°,所以传输一个扇区要 30、转一圈要 360)。时间 0 时磁头在外道、正对扇区 6 的中间。输入请求序列,逐步观察每个请求的寻道 旋转 传输。

模拟器

disk.py:请求序列、调度策略与三段时间

改请求、策略、寻道/旋转速率、磁道偏斜、调度窗口。每个请求分 4 步:调度器挑选 → 寻道 → 等旋转 → 传输;盘片和磁臂会动画移动。表格给出每个请求的 Seek / Rotate / Transfer / Total,与 disk.py 的输出格式相同。
原书作业 1:
原书示例:

动画里盘片逆时针转,磁头固定在右侧(3 点钟方向)沿半径方向移动(真实磁臂是绕轴摆动的,这里简化成直线)。浅色扇区是已服务的,橙色是还没服务的请求,深橙色是正在传输的扇区。

12先预测,再验证

(原书作业 1)默认参数下,分别计算 -a 0、-a 6、-a 30、-a 7,30,8、-a 10,11,12,13 的寻道、旋转、传输时间。提示:起点是扇区 6 的正中间,每扇区 30。
看答案
  • -a 0:Seek 0、Rotate 165(6 的后半 15 + 7…11 共 5×30)、Transfer 30、Total 195。
  • -a 6:Seek 0、Rotate 345(刚错过 6 的开头,要等 360−15)、Transfer 30、Total 375。
  • -a 30:Seek 80(两道 × 40)、Rotate 265、Transfer 30、Total 375。30 和 6 角度对齐,寻道 80 之后还得等到同一时刻 345。
  • -a 7,30,8:7 → (0, 15, 30, 45);30 → (80, 220, 30, 330);8 → (80, 310, 30, 420)。合计 Seek 160、Rotate 545、Transfer 90、Total 795。
  • -a 10,11,12,13:10 → (0, 105, 30, 135);11 → (0, 0, 30, 30);12 → (40, 320, 30, 390);13 → (0, 0, 30, 30)。合计 Seek 40、Rotate 425、Transfer 120、Total 585。
(原书作业 2)对 -a 7,30,8,把寻道速率改成 -S 2、4、8、10、40、0.1。先预测:寻道快 2 倍,总时间会少一半吗?
看答案

S=2:寻道合计 80,但 Total 仍是 795——省下的寻道时间全变成了旋转等待(30 和 8 都"早到了但扇区还没来")。S=4、8、10、40:Total 都是 435,因为从 30 到 8 寻道足够快,赶在 8 转过来之前就位,省掉了一整圈;之后再快也没用,瓶颈变成旋转。S=0.1:寻道 800 一次,Total 2235。结论:寻道和旋转是耦合的,只优化其中一项,收益可能是零,也可能是跳变。

(原书作业 3)还是 -a 7,30,8,把旋转速率改成 -R 0.1、0.5、0.01。时间怎么变?
看答案

转得越慢,旋转和传输都等比例变长:R=0.5 Total 1590,R=0.1 Total 4350,R=0.01 Total 43500。有意思的是 R=0.1 时第三个请求 8 只需旋转 220:寻道 80 这段时间盘几乎没转,等待模式完全不同。

(原书作业 4、5)-a 7,30,8 用 SSTF 和 SATF 各是什么顺序、多长时间?再找一组 SATF 明显优于 SSTF 的请求。
看答案

SSTF:7 和 8 都在当前磁道(距离 0),按队列顺序先 7 再 8,最后 30。7 → (0, 15, 30, 45);8 → (0, 0, 30, 30);30 → (80, 190, 30, 300);合计 Seek 80、Rotate 205、Transfer 90、Total 375(FIFO 是 795)。SATF 选出同样的顺序,也是 375。

SATF 胜出的例子:-a 0,20(默认参数)。SSTF 先做同道的 0(要等 165),Total 435;SATF 发现 20 寻道 40 后只需再等 5,先做 20,Total 195。或者用原书 Figure 37.8 的预设:S=4 时 SSTF 435 对 SPTF 315。一般地,当寻道相对旋转很快、而近处磁道上的请求刚刚错过时,SATF 更好。

(原书作业 6)-a 10,11,12,13 哪里表现差?加磁道偏斜能改善吗?默认寻道速率下偏斜设多少最好?S=2、S=4 时呢?能写出公式吗?
看答案

问题出在 11 → 12 跨磁道:寻道 40,而读完 11 时 12 的起点正好在磁头下,寻道完它已转过去,要等 320。偏斜试验结果(Total):S=1 时 skew 0/1/2/3 = 585/615/285/315,最佳 2;S=2 或 4 时 = 585/255/285/315,最佳 1。

公式:换一道的寻道时间是 40/S,这段时间盘转过 (40/S)·R 度,每扇区 30°,所以偏斜至少要 skew = ⌈(40 / S) · R / 30⌉ 个扇区。偏斜再大也不好:多等的每个扇区都是浪费。

用计算器:如果把 Cheetah 的随机请求从 4KB 改成 1MB,RI/O 变成多少?这说明了原书哪条 TIP?
看答案

1MB 的传输要 8ms,TI/O ≈ 4 + 2 + 8 = 14ms,RI/O ≈ 71MB/s,是 4KB 随机读的一百多倍。这就是"做不到顺序,至少用大块传输,越大越好":寻道和旋转是每个请求的固定成本,请求越大,固定成本被摊得越薄。

13动手实验:顺序读 vs 随机读

labs/37-hdd/seqrand.c 在当前目录写一个 128MB 的测试文件,然后用 O_DIRECT(绕过页缓存,每次读都真的到达设备)分别测:1MB 一次的顺序读、4KB 一次的顺序读、4KB 一次的随机读。测完自动删除文件。

cd labs/37-hdd && make && ./seqrand

示例输出(WSL2 · ext4,底层是 SSD 上的虚拟磁盘;你的机器上数字会不同):

测试文件 128 MB = 32768 个 4KB 块(O_DIRECT,绕过页缓存)

顺序读  1MB × 128   :     57.1 ms    2243.6 MB/s
顺序读  4KB × 4000  :    481.2 ms      32.5 MB/s  平均每次  120.3 us
随机读  4KB × 4000  :    648.9 ms      24.1 MB/s  平均每次  162.2 us

顺序(1MB) / 随机(4KB) 带宽比 ≈ 93 倍

怎么解读:

14自测题

1. 磁盘厂商保证什么样的写是原子的?
只有单扇区写是原子的。4KB 写跨越 8 个扇区,断电时可能只写了一部分(撕裂写),文件系统必须自己处理。
2. 一块 15000 RPM 的磁盘,平均旋转延迟是多少?
15000 RPM = 250 转/秒,一圈 4ms;平均要等半圈,即 2ms。4ms 是一整圈,6ms 是 10000 RPM 的一圈。
3. Cheetah 上随机 4KB 读的 TI/O ≈ 6ms,其中占比最小的是?
4KB 在 125MB/s 下只需约 30µs,而寻道 4ms、旋转 2ms。小随机 I/O 的时间几乎全花在机械定位上,这正是随机和顺序差几百倍的原因。
4. 磁道偏斜(track skew)要解决什么问题?
换道需要时间,偏斜让下一条磁道的起始扇区"晚一点"出现,磁头到位时恰好赶上。C 是多区(zone)的问题。
5. 关于 SSTF,下列说法错误的是:
SSTF 只看寻道距离,忽略了旋转(Figure 37.8 的例子),所以有了 SPTF。而且所有这些调度器都是贪心的,都不保证最优。
6. C-SCAN 相比 SCAN 的主要好处是?
SCAN 服务完最外道后要经过中间两次才回来,中间磁道被照顾得更频繁;C-SCAN 只单向扫、到头跳回,更公平。代价是回跳也要寻道。
7. 为什么 SPTF 通常在驱动器内部而不是 OS 里实现?
SPTF 需要精确估计旋转等待,这要求知道磁头此刻的角度和扇区布局,只有驱动器内部掌握。现代 OS 通常一次下发若干请求,让磁盘用 SPTF 排序。
8. 队列里依次有读块 33、8、34 的请求,OS 调度器应该先做什么优化?
这是 I/O 合并(merging):相邻块合成一个请求,减少发给磁盘的请求数、降低开销;排序再对合并后的请求进行。
9. 在默认 disk.py 模型下,寻道速率从 1 提高到 2(快一倍),-a 7,30,8 的总时间:
磁头提前到位,但目标扇区还没转过来,省下的寻道时间全部变成旋转等待。只有快到能"赶上"本来错过的那一圈时,总时间才会跳变(S≥4 时降到 435)。

15常见误区与本章小结

本章要点

和后续章节的联系:单块磁盘不够大、不够快、也不够可靠,下一章 RAID 把多块磁盘组合成一个"更好的磁盘",分析时直接沿用本章的 S(顺序带宽)和 R(随机带宽)。第 41 章 FFS 会利用"相邻块访问快"来布局文件;第 43 章 LFS 则把所有写都变成顺序写,把这一章的"顺序地使用磁盘"推向极致。