第一百四十七章:SCSI
合道期涉及内核源码:
一
林小源走出调度广场,面前出现了一条宽阔的大道。大道两侧竖着巨大的路标,路标上统一标注着 "SCSI" 的字样——无论是 SATA 硬盘、SAS 阵列还是 USB 闪存,所有的存储设备都在这条大道上通行。
一个穿着蓝色制服的中年人站在大道中央,手中拿着一本厚厚的登记册。他的制服左臂上绣着三层纹路——上层、中层、下层。
"我是 SCSI 核心。"中年人翻开登记册,"你看到的 /dev/sda、/dev/sdb,都是从我这里登记出去的。"
林小源注意到大道上方悬浮着一块巨大的牌匾,上面写着各种命令:READ(10)、WRITE(10)、INQUIRY、TEST UNIT READY。
"这些命令——所有存储设备都用同一套?"林小源问。
SCSI 核心点了点头:"不管是 SATA 硬盘还是 USB 闪存,到了我这里都说同一种语言。上层的驱动——sd、sr、st——通过我下发命令;下层的适配器驱动通过我接收命令。我就是翻译。"
一个穿着白色长袍的年轻人从大道左侧走来,胸口绣着 "sd" 两个字母。他身后跟着一队排着整齐队列的 SCSI 命令。
"sd 是磁盘驱动,"SCSI 核心介绍道,"你每次读写 /dev/sda,都是 sd 在和我打交道。"
年轻人朝林小源点了点头,然后翻开一本小册子,上面记录着每条 READ(10) 命令的 LBA 地址和传输长度。
"还有 sr——光驱驱动。"SCSI 核心指向大道右侧一个背着圆盘的矮个子,"以及 st——磁带驱动。"远处一个扛着卷轴的老人正在缓慢地走来。
林小源仰头望向大道尽头,那里的路标分成了两条岔路:一条继续通往传统的 SCSI 通道,另一条通往一条更宽、更快的新路,路标上写着 "NVMe"。
"NVMe 不走你这条路?"林小源问。
SCSI 核心的表情有些复杂:"NVMe 有自己的路——专门为闪存设计,延迟更低,并行度更高。但在 Linux 里,很多存储设备还是通过我访问。我老了,但还没退休。"
林小源暗自感叹,搞了半天,SCSI 就是存储世界的通用语言。
/*
* SCSI 子系统:
*
* SCSI 上层: sd (磁盘), sr (光驱), st (磁带)
* SCSI 中层: SCSI 核心
* SCSI 下层: host adapter 驱动
*
* SCSI 命令:
* READ(10) — 读取数据
* WRITE(10) — 写入数据
* INQUIRY — 查询设备信息
* TEST UNIT READY — 测试设备就绪
*
* SCSI 的意义:
* 统一的存储接口
* 支持多种设备
* 支持多种传输方式
*/
printf("=== SCSI — 存储的通用框架 ===\n\n");
printf("SCSI 子系统:\n\n");
printf(" SCSI 上层:\n");
printf(" sd — 磁盘\n");
printf(" sr — 光驱\n");
printf(" st — 磁带\n\n");
printf(" SCSI 中层:\n");
printf(" SCSI 核心\n\n");
printf(" SCSI 下层:\n");
printf(" host adapter 驱动\n\n");
printf("--- SCSI 命令 ---\n");
printf("READ(10): 读取数据\n");
printf("WRITE(10): 写入数据\n");
printf("INQUIRY: 查询设备信息\n");
printf("TEST UNIT READY: 测试就绪\n\n");
printf("--- SCSI 的意义 ---\n");
printf("统一的存储接口:\n");
printf(" 不管底层是什么\n");
printf(" 上层都看到 SCSI 设备\n\n");
printf("支持多种设备:\n");
printf(" SATA 硬盘\n");
printf(" SAS 硬盘\n");
printf(" USB 存储\n");
printf(" NVMe (部分)\n\n");
printf("--- /dev/sd* ---\n");
printf("/dev/sda — 第一块 SCSI 磁盘\n");
printf("/dev/sdb — 第二块 SCSI 磁盘\n");
printf("/dev/sda1 — 第一块磁盘的第一个分区\n\n");
printf("--- SCSI vs NVMe ---\n");
printf("SCSI:\n");
printf(" 通用存储框架\n");
printf(" 支持多种设备\n\n");
printf("NVMe:\n");
printf(" 专门为闪存设计\n");
printf(" 更低延迟\n");
printf(" 更高并行度\n");#include <stdio.h>
/*
* SCSI 子系统:
*
* SCSI 上层: sd (磁盘), sr (光驱), st (磁带)
* SCSI 中层: SCSI 核心
* SCSI 下层: host adapter 驱动
*
* SCSI 命令:
* READ(10) — 读取数据
* WRITE(10) — 写入数据
* INQUIRY — 查询设备信息
* TEST UNIT READY — 测试设备就绪
*
* SCSI 的意义:
* 统一的存储接口
* 支持多种设备
* 支持多种传输方式
*/
int main() {
printf("=== SCSI — 存储的通用框架 ===\n\n");
printf("SCSI 子系统:\n\n");
printf(" SCSI 上层:\n");
printf(" sd — 磁盘\n");
printf(" sr — 光驱\n");
printf(" st — 磁带\n\n");
printf(" SCSI 中层:\n");
printf(" SCSI 核心\n\n");
printf(" SCSI 下层:\n");
printf(" host adapter 驱动\n\n");
printf("--- SCSI 命令 ---\n");
printf("READ(10): 读取数据\n");
printf("WRITE(10): 写入数据\n");
printf("INQUIRY: 查询设备信息\n");
printf("TEST UNIT READY: 测试就绪\n\n");
printf("--- SCSI 的意义 ---\n");
printf("统一的存储接口:\n");
printf(" 不管底层是什么\n");
printf(" 上层都看到 SCSI 设备\n\n");
printf("支持多种设备:\n");
printf(" SATA 硬盘\n");
printf(" SAS 硬盘\n");
printf(" USB 存储\n");
printf(" NVMe (部分)\n\n");
printf("--- /dev/sd* ---\n");
printf("/dev/sda — 第一块 SCSI 磁盘\n");
printf("/dev/sdb — 第二块 SCSI 磁盘\n");
printf("/dev/sda1 — 第一块磁盘的第一个分区\n\n");
printf("--- SCSI vs NVMe ---\n");
printf("SCSI:\n");
printf(" 通用存储框架\n");
printf(" 支持多种设备\n\n");
printf("NVMe:\n");
printf(" 专门为闪存设计\n");
printf(" 更低延迟\n");
printf(" 更高并行度\n");
return 0;
}二
林小源跟着 SCSI 核心走进了大道旁的一座三层建筑。建筑内部的结构清晰地分为三层——底层是适配器驱动的工作间,中层是 SCSI 核心的调度大厅,上层是设备驱动的办公区。
"分层是我的立身之本。"SCSI 核心站在中层大厅里,指着脚下的地板和头顶的天花板,"底下的人只管和硬件打交道,上面的人只管和文件系统打交道。两边都不需要知道对方是谁——只要把命令交给我就行。"
林小源走到一个窗口前,看到下层的一个适配器驱动正在把一批 SCSI 命令翻译成 SATA 协议的帧格式,然后通过一条细长的通道发送出去。通道的另一端是一块真正的硬盘。
"如果换了 SAS 硬盘呢?"林小源问。
"换一个适配器驱动就行,"SCSI 核心说,"上层的 sd 驱动什么都不用改。它只看到 SCSI 命令,不关心底层是 SATA 还是 SAS。"
一个穿着灰色工装的适配器驱动从楼下走上来,手里拿着一张新的协议卡:"新到了一批 USB 存储设备,我刚把 USB Mass Storage 的翻译规则配好。"
SCSI 核心接过协议卡看了一眼,点了点头,然后在登记册上添了几行。整个过程行云流水——上层的 sd 驱动甚至没有抬头看一眼。
林小源站在三层建筑的窗口前,若有所思——分层才是通用的根基。
三
林小源离开 SCSI 大道,走向 NVMe 的新路。新路的路面更加平整,车道也更宽——至少有六十四车道并排。
NVMe 的路标旁站着一个年轻的管理员,穿着银灰色的制服,脸上带着自信的微笑。
"NVMe 是为闪存设计的全新协议,"年轻人说,"SCSI 是为机械盘时代设计的——它的命令队列深度有限,协议开销也大。NVMe 直接走 PCIe 总线,队列深度可以到几万,延迟是 SCSI 的几分之一。"
林小源回头望了望 SCSI 大道。那条路上依然车水马龙——SATA 硬盘、SAS 阵列、USB 闪存,各种设备排着队通过 SCSI 核心的检查站。
"SCSI 会被淘汰吗?"林小源问。
NVMe 年轻人摇了摇头:"在 Linux 里,SG(通用 SCSI 层)仍然覆盖着大量设备。NVMe 很快,但 SCSI 的通用性是它比不了的。两条路会共存很久。"
林小源站在两条路的交叉口,看着新旧两代协议各司其职。SCSI 大道沉稳而包容,NVMe 新路迅捷而专精——它们不是替代关系,而是互补。
新旧两代协议不是替代关系,而是各有所长、长期共存。
道藏笔记
内核启示
SCSI 在 Linux 存储世界里的地位,大概相当于普通话在中国的地位——不管你底层是 SATA 硬盘、SAS 阵列还是 USB 闪存,到了 SCSI 这一层都说同一种语言。它分三层:上层是具体的设备驱动,sd 管磁盘、sr 管光驱、st 管磁带;中层是 SCSI 核心,负责翻译和调度;下层是适配器驱动,跟具体的硬件打交道。分层的好处是换硬件只需换下层驱动,上层代码一行不用改。NVMe 虽然更快更专精,但 SCSI 的通用性短期内没人能替代——两条路会共存很久。
SCSI 之试
磁盘、光驱等块设备常通过哪套分层存储协议进入 Linux 块层?