Linux SCSI子系统是一种分层的架构,如图所示:
(图片上传到Linux系统教程频道。)
共分为三层。
Lower level层:代表适用于SCSI的物理接口的实际驱动器。底层驱动的主要作用是发现连接到主机适配器后面的SCSI设备,在内存中为它们建立好数据结构,并提供消息传递接口,将SCSI命令的接收与发送解释为主机适配器的操作。
Upper level层:
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 中间层是 SCSI 较高层和较低层的公共服务层(可以在 ./linux/drivers/scsi/scsi.c 内部分地实现)。它提供了很多可供较高层和较低层驱动器使用的函数,因而可以充当这两层间的连接层。中间层很重要,原因是它抽象化了较低层驱动器(LLD)的实现,可以在 ./linux/drivers/scsi/hosts.c 中部分地实现。这意味着可以以同样的方式使用带不同接口的 Fibre Channel 主机总线适配器(HBA)。
SCSI子系统的源代码位于目录drivers/scsi/下,头文件在include/scsi/目录下。SCSI子系统的主要功能是:
探测SCSI设备,在内存系统中构造SCSI子系统的目录树;
在sysfs文件系统中构造SCSI子系统的目录
SCSI高层驱动绑定SCSI设备,在内存中构建对应的核心结构;
提供错误恢复API,在SCSI命令错误和超时后被调用。