您的位置首页>企业动态>

Linux SCSI子系统剖析

导读 大家好,我是极客范的本期栏目编辑小友,现在为大家讲解Linux SCSI子系统剖析问题。小型计算机系统接口(SCSI)是一套标准,它定义了与大量

大家好,我是极客范的本期栏目编辑小友,现在为大家讲解Linux SCSI子系统剖析问题。

小型计算机系统接口(SCSI)是一套标准,它定义了与大量设备(主要是与存储相关的设备)通信所需的接口和协议。Linux为与这些设备通信提供了一个SCSI子系统。Linux是分层体系结构的一个很好的例子,它将高级驱动器(如磁盘驱动器或光盘驱动器)连接到物理接口,如光纤通道或串行连接SCSI(SAS)。本文向大家介绍了Linux SCSI子系统,并讨论了这些子系统未来的发展方向。GNU/Linux和SCSI是一个很好的组合,因为它们在各自的环境中具有相似的特性。GNU/Linux是一个安全可靠的操作系统,可以连续运行。SCSI适用于可靠和高性能的存储。两者都是开源的。您可以下载并查阅国际信息技术标准委员会(incits) T10技术委员会的各种SCSI规范。同样,你也可以下载GNU/Linux源代码来了解它的实现。它们在各自的行业中占据主导地位,所以GNU/Linux能够比其他操作系统更好地支持SCSI也就不足为奇了。

SCSI的演变

SCSI是一个非常有趣的接口,它是早期的接口之一,目前仍在发展中。第一个SCSI标准被称为SCSI-1,由舒加特协会在1979年左右创建。SCSI-1定义了一个具有5MHz数据时钟的8位并行接口,可以提供每秒5字节(5 MB/s)的最高数据传输速率。

SCSI-2标准出现在1985年,它使数据速率更快(10MHz),总线更宽(16位)。SCSI-2被称为Fast/Wide,允许高达20 MB/s的数据传输速率,并与SCSI-1向后兼容,但该速率也将受限于SCSI-1的数据速率。

SCSI-3的开发始于1993年,现在已经成为一套标准,可以定义协议、命令集和信令方法。SCSI-3包括一套名为Ultra的并行SCSI标准和基于串行SCSI的协议,如IEEE 1394(火线)、光纤通道、互联网SCSI (iSCSI)和新兴的SAS。这些标准通过引入存储网络技术(如FC-AL或iSCSI),将数据速率扩展到1gb/s,将可寻址设备的最大数量增加到100个以上,并将最大电缆长度扩展到25米,改变了传统的存储概念。图1显示了从1986年到2007年SCSI数据速率的变化。

1.SCSI数据速率的演变。

SCSI工作原理。

SCSI实现了客户端/服务器风格的通信架构。启动器向目标设备发送命令请求。目标处理请求并向发起方返回响应。启动器可以是被管理计算机中的SCSI设备,而SCSI目标可以是磁盘、光盘、磁带设备或特殊设备(如盒式设备)。

SCSI命令

SCSI传输中使用的协议随着时间的推移而改变,但SCSI命令保留了原始元素。SCSI命令在命令描述符块(CDB)中定义。CDB包含定义要执行的特定操作的操作代码,以及大量特定于操作的参数。

SCSI命令支持读写数据(每个有四个变量)和许多非数据命令,如测试单元就绪、查询、读取容量等。目标设备支持什么命令取决于设备的类型。启动器通过查询命令识别设备类型。表1列出了最常用的SCSI命令。

1.常见的SCSI命令。

使用测试装置准备询问设备是否准备好传输。询问设备的基本信息。请求前一个命令的错误信息。读取容量请求存储容量信息。从设备中读取数据。将数据写入设备。请求检测页面(设备参数)。模式选择在模式页面上配置设备参数。

大约有60个可用的命令。

CSI 可适用于许多设备(包括随机存取设备,比如磁盘和像磁带这样的顺序存储设备)。SCSI 也提供了专门的命令以访问箱体服务(比如存储箱体内部当前的传感和温度)。

 

Linux 内核中的 SCSI 架构

图 2 显示了 SCSI 子系统在 Linux 内核中的位置。内核的顶部是系统调用接口,处理用户空间调用到内核中合适的目的地的路由(例如 open、read 或 write)。而虚拟文件系统(VFS) 是内核中支持的大多数文件系统的抽象层。它负责将请求路由到合适的文件系统。大多数文件系统都通过缓冲区缓存来相互通信,这种缓存通过缓存最近使用的数据来优化对物理设备的访问。接下来是块设备驱动器层,它包括针对底层设备的各种块驱动器。SCSI 子系统是这种块设备驱动器之一。

图 2. SCSI 子系统在 Linux 内核中的位置 

与 Linux 内核中的其他主流子系统不同,SCSI 子系统是一种分层的架构,共分为三层。顶部的那层叫做较高层,代表的是内核针对 SCSI 和主要设备类型的驱动器的最高接口。接下来的是中间层,也称为公共层或统一层。在这一层包含 SCSI 堆栈的较高层和较低层的一些公共服务。最后是较低层,代表的是适用于 SCSI 的物理接口的实际驱动器(参见图 3)。

图 3. Linux SCSI 子系统的分层架构 

在 ./linux/drivers/scsi 可以找到 SCSI 子系统(SCSI 较高层、中间层和各种驱动器)的源代码。SCSI 数据结构则位于 SCSI 源目录,在 ./linux/include/scsi 也可以找到。

 

SCSI 较高层

SCSI 子系统的较高层代表的是内核(设备级)最高级别的接口。它由一组驱动器组成,比如块设备(SCSI 磁盘和 SCSI CD-ROM)和字符设备(SCSI 磁带和 SCSI generic)。较高层接受来自上层(比如 VFS)的请求并将其转换成 SCSI 请求。较高层负责完成 SCSI 命令并将状态信息通知上层。

SCSI 磁盘驱动器在 ./linux/drivers/scsi/sd.c 内实现。SCSI 磁盘驱动器通过调用 register_blkdev(作为块驱动器)进行自初始化并通过 scsi_register_driver 提供一组函数以表示所有 SCSI 设备。其中 sd_probe 和 sd_init_command 这两个函数很重要。只要有新的 SCSI 设备附加到系统, SCSI 中间层就会调用 sd_probe 函数。sd_probe 函数可决定此设备是否由 SCSI 磁盘驱动器管理,如果是,就创建新的 scsi_disk 结构来表示它。sd_init_command 函数将来自文件系统层的请求转变成 SCSI 读或写命令(为完成这个 I/O 请求,sd_rw_intr 会被调用)。

SCSI 磁带驱动器在 ./linux/drivers/scsi/st.c 内实现。磁带驱动器是顺序存取设备,会通过 register_chrdev_region 将自身注册为字符设备。SCSI 磁带驱动器还提供了一个 probe 函数,称为 st_probe。该函数会创建一种新磁带设备并将其添加到称为 scsi_tapes 的向量。SCSI 磁带驱动器的独特之处在于,如果可能,它可以直接从用户空间执行 I/O 传输。否则,数据会通过驱动器缓冲被分段。

SCSI CD-ROM 驱动器在 ./linux/drivers/scsi/sr.c 内实现。CD-ROM 驱动器是另一种块设备并为 SCSI 磁盘驱动器提供类似的函数集。sr_probe 函数可用来创建 scsi_sd 结构以表示 CD-ROM 设备,并用 register_cdrom 注册此 CD-ROM。SCSI 磁带驱动器还会导出 sr_init_command,以将请求转换成 SCSI CD-ROM 读或写请求。

SCSI generic 驱动器在 ./linux/drivers/scsi/sg.c 内实现。该驱动器允许用户应用程序向设备发送 SCSI 命令(比如格式化、模式感知或诊断命令)。通过 sg3uTIls 包还可以从用户空间利用 SCSI generic 驱动器。这个用户空间包包括多种实用工具,可用来发送 SCSI 命令和解析这些命令的响应。

 

SCSI 中间层

SCSI 中间层是 SCSI 较高层和较低层的公共服务层(可以在 ./linux/drivers/scsi/scsi.c 内部分地实现)。它提供了很多可供较高层和较低层驱动器使用的函数,因而可以充当这两层间的连接层。中间层很重要,原因是它抽象化了较低层驱动器(LLD)的实现,可以在 ./linux/drivers/scsi/hosts.c 中部分地实现。这意味着可以以同样的方式使用带不同接口的 Fibre Channel 主机总线适配器(HBA)。

低层驱动器注册和错误处理都由 SCSI 中间层提供。中间层还提供了较高层和较低层间的 SCSI 命令排队。SCSI 中间层的一个重要功能是将来自较高层的命令请求转换成 SCSI 请求。它也负责管理特定于 SCSI 的错误恢复。

中间层可以连接 SCSI 子系统的较高层和较低层。它接受对 SCSI 事务的请求并对这些请求进行排队以便处理 (如 ./linux/drivers/scsi/scsi_lib.c 中所示)。当这些命令完成后,它接受来自 LLD 的 SCSI 响应并通知较较高层此请求已经完成。

中间层最重要的职责之一是错误和超时处理。如果 SCSI 命令没有在合理的时间内完成或者 SCSI 请求返回错误,中间层就会管理错误或重新发送此请求。中间层还可管理较高层恢复,比如请求 HBA (LLD) 或 SCSI 设备重置。SCSI 错误和超时处理程序在 ./linux/drivers/scsi/scsi_error.c 内实现。

 

SCSI 较低层

在最低层的是一组驱动器,称为 SCSI 低层驱动器。它们是一些可与物理设备(比如 HBA)链接的特定驱动器。LLD 提供了自公共中间层到特定于设备的 HBA 的一种抽象。每个 LLD 都提供了到特定底层硬件的接口,但所使用的到中间层的接口却是一组标准接口。

较低层包含大量代码,原因是它要负责处理各种不同的 SCSI 适配器类型。例如,Fibre Channel 协议包含了针对 Emulex 和 QLogic 的各种适配器的 LLD。面向 Adaptec 和 LSI 的 SAS 适配器的 LLD 也包括在内。

 

Linux 和 SCSI 的未来展望

毫无疑问,SCSI 的发展前景很好,并且它会与 Linux 紧密相关。随着 SCSI 的演化,Linux 将会一如既往地为不断发展的技术提供支持。Linux 借助面向 HBA 的驱动器为新的 SAS 协议提供支持。随着协议向更快的速度发展(比如 6 Gb SAS 或 8 Gb FC),Linux 必将处在发展和部署的前沿。

您还会发现 Linux 恰恰就是新 SCSI 协议的先进之处。FCoE(Fibre Channel over Ethernet)颇值得一提。FCoE 是全双工 Ethernet 网络(通常是 1Gb 或 10Gb Ethernet)上的一种 Fibre Channel 框架的映射。FCoE 之所以重要,是因为它将主流的网络媒介与主流的企业存储协议连接起来。这种新技术必然受人瞩目,而且 Linux 也将不会例外。

针对 SCSI 的端到端数据保护也在开发中,它源于 T10 的新数据完整性标准。这个标准为每扇区都增加了一个数据完整性字段(DIF)以保护介质上的数据。这个新的 8 字节 DIF 字段包括一个循环冗余代码(CRC)用以保护数据,一个参考标签用以保护数据免遭误导写入,以及一个应用程序标签。应用程序标签特定于应用程序,并且可以定义数据的用途,例如,一个 PDF 文件的一部分。

 

结束语

Linux 内核是抽象的分层结构的另一个典型示例。它将各种文件系统连接到不同的物理存储介质。若这些存储介质与 SCSI 相关,SCSI 子系统会将公共 Linux 块请求转化为针对特定底层设备的 SCSI 请求。SCSI 子系统本身在过去若干年中经历了很多变化,而且这些变化还在继续。诸如端到端数据保护这样的新技术,与 FCoE 这样的新协议一样,都在想方设法寻找与 Linux 建立关系的途径。

郑重声明:本文版权归原作者所有,转载文章仅为传播更多信息之目的,如作者信息标记有误,请第一时间联系我们修改或删除,多谢。