1. SCSI协议简介
小型计算机系统接口(SCSI,Small Computer System Interface)是一种用于计算机及其周边设备之间(硬盘、软驱、光驱、打印机、扫描仪等)系统级接口的独立处理器标准。虽然名字里面带个接口,但实际上是一种应用层协议。简单理解,就是系统想要跟任何硬件进行数据交互的话,都是通过SCSI协议来进行的,通过这样的分层,在系统不需要去适配各种各样的通信总线协议。
1.1 SCSI协议结构
SCSI由于其海纳百川的拓展性和兼容性,其协议结构非常的庞大,下图展示了一部分SCSI协议的内容:
从上图可以看到,向上SCSI提供了非常多的驱动规范给系统,以便能胜任各种系统需求。向下SCSI又提供了非常多的传输层协议,以便能够适配各种各样的传输总线,而上图还没有完全展示出SCSI支持的所有传输总线类型。
看到这个图很有可能会两眼一黑(最起码我就是),但是看过其中一些协议之后,会发现种类虽然比较多,但是都存在一些共性,毕竟都是围绕着同样的SCSI命令传输来设计的。
所以在最开始了解SCSI时,可以先了解一下SCSI自身的一些相关规范。
1.1.1 SCSI Architecture Model
定义了SCSI自身最基本标准的,就是SCSI Architecture Model(SAM)规范,其中包含了SCSI系统模型,SCSI标准的功能分区,以及适用于所有SCSI实现和试试标准的要求。
其中比较具有代表性的,比如定义了什么是CDB(Command Descripotr Block),CDB即为定义设备在收到后所需要进行的操作,也就是SCSI命令。但是CDB的结构长什么样,要在另外一份SCSI Primary Commands(SPC)文档当中查找:
这份文档给出了CDB的结构,可以看到对于CDB只有一条强制规定,就是首个字节必须为OPERATION CODE(Opcode),并且CDB长度有6、10、12、16字节长度的类型。
SAM当中还定义了Status codes,用来标记SCSI命令传输的状态:
最重要的,是定义了一个完整的SCSI命令传输,必须包含的阶段:
- 命令发送请求(Send SCSI Command request)
- 命令接收标志(SCSI Command Received indication)
- 命令发送完成响应(Send Command Complete response)
- 命令完成确认(Command Complete Received confirmation)
原文如下:
All SCSI transport protocol standards shall define the SCSI transport protocol specific requirements for implementing the Send SCSI Command request (see 5.4.2.2), the SCSI Command Received indication (see 5.4.2.3), the Send Command Complete response (see 5.4.2.4), and the Command Complete Received confirmation (see 5.4.2.5) SCSI transport protocol services.
也就是说不管是什么样的传输协议,如果要适配SCSI命令,就必须想各种办法来实现这4个小目标才能实现SCSI命令传输。
1.1.2 Command Set
由于SCSI所支持的设备类型非常多样,不同的设备作用范围不一样,因此SCSI给不同类型的设备划分了需要支持的SCSI命令集。像上一节提到的SPC,表示SCSI主要的命令,各种设备都需要或多或少的支持一些其中的命令。
其他类型的命令集有例如给存储设备使用的SBC(SCSI Block Command),给多媒体设备所使用的MMC(Multi-media Command)等等。
1.2 T10
既然介绍到SCSI了,就在介绍一下负责定义SCSI的组织:T10。T10是INCITS(InterNational Committee on Information Technology Standards)中的一个技术委员会,而INCITS又遵循ANSI(American National Standards Institute),所以最终还是一个美国协会。
理论上所有与SCSI相关的技术规范都可以在T10官网上找到(还得有权限。),而INCITS除了有T10,还有负责光纤通讯规范的T11,负责ATA/SATA规范的T13等等。
1.3 SCSI在系统中的层级
在Windows Storage Driver Architecture当中,最开始就介绍了Windows系统是如何通过层层驱动最终获取到硬件设备数据的:
最上层的IRP,即为I/O Request Packet,是Windows系统当中描述I/O数据请求的数据结构,Windows系统将数据请求通过IRP发送给存储类型驱动,也就是SCSI处理器。SCSI处理器在收到数据请求后根据不同的类型又转换成SRBs(SCSI Request Block),然后再经过了若干个驱动转换最终到达数据存储端口(Storage port driver)。
当SRB到达Storage prot driver之后,就会开始根据硬件设备所用的传输总线来区分不同的SRB传输方式了,在这当由于SCSI的普适性,有着各种各样的封装和转换,接下来将会挑一些比较常见的(我学得会的…)来介绍一下SCSI和这些协议的承接关系,希望能够扩展一些相关概念。
2. SCSI与多种数据总线关系
2.1 SCSI与USB & UFS
之所以将USB和UFS放在一个章节来介绍与SCSI的关联,是因为这两个协议都是采用了相似的方式,将SCSI的CDB进行了一次封装来进行传递的。也就是说USB和UFS设备,连接到以SCSI为数据交互的操作系统当中时,设备端最终解析的是经过封装的CDB。
2.1.1 SCSI与USB
从SCSI到USB,中间夹着一层有两种实现方式的传输协议,一种是BOT(Bulk-Only Transport),另一种是UAS(USB Attached SCSI)。BOT诞生的时间较早,定义于1999年。而UAS的话则年轻得多,与USB3.0一样定义于2008年。可能是得益于时代的进步,UAS的规范文档相较于BOT来讲要容易阅读一些,相关概念介绍的也比较清晰,为了防止产生误解,接下来会以UAS为例来介绍USB和SCSI的关联。
在1.1.1节中有介绍如何定义一个完整的SCSI命令传输,UAS为了适配这样的规则,在基于USB协议的基础上,给出了这样的一份适配方案:
- 命令发送请求(Send SCSI Command request) – Command Block Wrapper(COMMAND IU)
- 命令接收标志(SCSI Command Received indication) – 收到COMMAND IU的ACK
- 命令发送完成 (Send Command Complete response) – Command Status Wrapper(SENSE IU)
- 命令完成确认(Command Complete Received confirmation) – 收到SENSE IU的ACK
在这当中,IU(Information Unit)为UAS协议的内容,ACK(Acknowledge)为USB协议的内容。UAS通过这样的方式来完成一次SCSI完整命令传输的适配。
2.2.2 SCSI与UFS
UFS(Universal Flash Storage)规范定义于2011年,作为一个比较新的协议,从定义的时候就考虑清楚了要如何适配SCSI。因此在UFS的规范文档当中,UTP层(UFS Transport Protocol Layer)的描述就包含了SCSI的SAM相关说明。在UFS当中,SCSI命令传输所用到的相关信息如CDB,Status在UTP层被封装到UPIU(UFS Protocol Information Units )进行传输。
UFS如何适配一次完整的SCSI命令传输,UFS规范文档当中也直接以一份示例图来展现:
2.2 SCSI与ATA
ATA是Advanced Technology Attachment的缩写,是一种定义IDE设备的规范。旧的规范有PATA,即Parallel ATA,是一种并行的ATA接口,流行于上世纪80年代,现在已经基本没有电脑支持这个接口了。在PATA之后定义的SATA(Serial ATA)规范应该是更广为人知的,SATA作为串行接口,解决了并行接口信号串扰的问题,通信效率更高。
尽管Windows系统都在使用SCSI,很多电脑上也使用的是SATA的硬盘,但是SCSI与SATA并没有经过一个传输层协议的封装。
2.2.1 SCSI与SATA
SCSI与SATA的转换关系,正是准备要说的第二类SCSI连接方式,就是协议转换。使用SATA作为数据总线的设备,并不会收到SCSI发起端发送的SCSI命令,也就不会接收到SCSI的CDB,SATA设备解析的是ATA指令集。而SATA与SCSI的通信方式,是通过一层叫做SAT(SCSI ATA Translation)规范来定义的。
在SAT规范当中,明确规定了需要将哪些SCSI命令转换成ATA命令来进行数据传输,SAT-2当中很明确的给出了需要进行命令转换的列表:
不同的命令规定了不同的转换方式,其中比较特殊的命令是ATA PASS-THROUGH,与2.1当中传输层协议封装CDB相反,SCSI为了让主机能够发送指定的ATA命令,使用CDB在封装ATA命令下发到设备:
到这里可以看到,SCSI和ATA是一种命令转换的关系,与之比较类似的还有SCSI到NVMe的NVM Express:SCSI Translation。
随着SCSI和SATA逐渐普及,这之间却没有一个高效的桥梁,另外考虑到SATA本身也有一部分限制,比如只能半双工工作,因此在这样的需求下,又推出了兼容SATA的SAS(Serial Attached SCSI)规范。
2.2.2 SCSI与SAS
SAS可以兼容SATA的物理接口,接口速率最高都是6Gb/s,但是由于SAS对命令流处理优化,SAS硬盘的速度通常比SATA要高一些。
SAS与SCSI就跟USB/UFS一样,采用的是将CDB封装最终传输给设备进行SCSI命令解析的方式。同样的,SAS要想完整的进行SCSI命令传输,也需要适配SCSI传输的最基本4个阶段,SAS给出的适配方式如下:
- 命令发送请求(Send SCSI Command request) – Command frame
- 命令接收标志(SCSI Command Received indication) – Command frame ACK
- 命令发送完成 (Send Command Complete response) – Response frame
- 命令完成确认(Command Complete Received confirmation) – Response frame ACK
这里面的Command frame为SAS协议规定封装了CDB的数据结构,另外还包含了SCSI命令传输所需要的一些参数:
2.3 SCSI与TCP/IP
额外再把SCSI与TCP/IP的关系拿出来说一下,是单纯觉得SCSI的扩展性实在是太广泛了。SCSI与TCP/IP也是经过了一层封装协议,叫做iSCSI(Internet SCSI),经过iSCSI封装后,数据通过TCP/IP传输,能够将远程网络盘直接显示成电脑上的本地硬盘!
这种通过网络连接来附加存储的方式被称为NAS(Network Attached Storage),iSCSI是实现NAS的一种方式,另外还有iFCP、FCIP等标准。除了NAS,还有SAN(Storage Area Network)也能实现远程存储,不得不说互联网确实是热门行业,连实现方案都五花八门。
3. 结语
SCSI现在作为一种应用非常广泛的OS数据传输规范,以后只会更多的适配各种各样的传输总线,但是只要了解了SCSI本身的基本结构和两种与SCSI进行连接的方式(封装或转换),新的规范都需要适配SCSI自身的标准,学习起来也就没有太大的难度了。希望这篇文章能够以我比较浅薄的认识来给大家普及一些基本的概念和方法,为开发者们提供新的思路。
参考文档
Universal Flash Storgae(UFS)
Universal Serial Bus 3.2 Specification(USB3.2)
Universal Serial Bus Mass Storage Class Specification Overview
USB Attached SCSI - 2
Universal Serial Bus Mass Storage Class Bulk-Only Transport(BOT)
Storage driver design guide
Serial Attached SCSI Standard(SAS)
Serial ATA
NVM Express: SCSI Translation Reference
iSCSI Implementation and Best Practices on IBM Storwize Storage Systems
SCSI / ATA Translation - 2(SAT-2)
SCSI / ATA Translation - 3(SAT-3)
SCSI Architecture Model - 4(SAM - 4)
SCSI Primary Commands - 4(SPC - 4)
SCSI Block Commands - 3 (SBC-3)
为了方便大家学习(顺便捞点分),以上大部分参考文档已经上传资源,链接:
https://download.csdn.net/download/polley88/87814966