9.4. 通用驱动程序 (sg)

所有类型的 SCSI 设备都可以通过 sg 驱动程序访问。这意味着像 CD-ROM 驱动器这样的设备可以通过 sr 和 sg 驱动程序访问。其他 SCSI 设备,如扫描仪,只能通过 sg 驱动程序访问。sg 驱动程序能够识别 256 个 SCSI 设备。在加载 sg 驱动程序后,可以添加任意数量的设备(最多 256 个,总体限制)。

请参阅参考 W4 以获取 SCSI 通用 (sg) 驱动程序文档(在那里还可以找到 sg_utils 包)。关于 SCSI 标准,请参阅参考 W1;关于 SCSI 编程和直通机制主题的书籍,请参阅参考 B3

lk 2.4 中的 sg 驱动程序是“版本 3”,它添加了一个额外的接口结构和一些新的 ioctl()。最有趣的新 ioctl() 是 SG_IO,它发送 SCSI 命令并等待其响应。有关 sg 驱动程序的完整描述,请参阅 Linux 文档项目站点: www.tldp.org/HOWTO/SCSI-Generic-HOWTO/。本文档的(可能更新的)版本可以在 www.torque.net/sg/p/sg_v3_ho.html 找到。

缩写 “sg” 在内核中用于指代 SCSI 通用驱动程序和许多现代 IO 设备提供的分散-聚集功能(通常与 DMA 相关联)。上下文通常会明确指出指的是哪一个。例如,请注意名为 SG_GET_SG_TABLESIZE 的复杂的 sg ioctl(),其中第二个 “SG” 指的是分散-聚集。

sg 的公共接口位于文件/usr/src/linux/include/scsi/sg.h。根据发行版,这可能包含或不包含与/usr/include/scsi/sg.h相同的信息,它由 GNU 库维护者控制。如果这两个文件不相同,请使用前一个头文件。那些基于 sg 编写应用程序的人应该查阅其文档以了解更多关于此事项的信息。

sg 驱动程序会注册所有检测到的 SCSI 设备(当前最多 256 个)。每个新注册的 SCSI 设备都会被分配下一个可用的次设备号。至少在最初,这将与设备在中层 cat /proc/scsi/scsi 中显示的顺序相同。sg 设备的设备映射可以通过 cat /proc/scsi/sg/devices cat /proc/scsi/sg/device_strs 查看。当移除底层驱动程序(例如 rmmod aha1542)或使用 remove-single-device 移除设备时,cat /proc/scsi/scsi 和 sg 排序之间的差异将出现。sg 驱动程序将保持剩余 SCSI 设备到次设备号的映射不变。这可能会在 sg 映射中留下一个“空洞”。下面是一个例子。

$ cat /proc/scsi/scsi 
Attached devices: 
Host: scsi0 Channel: 00 Id: 00 Lun: 00
  Vendor: IBM      Model: DNES-309170W     Rev: SA30
  Type:   Direct-Access            ANSI SCSI revision: 03
Host: scsi1 Channel: 00 Id: 02 Lun: 00
  Vendor: PIONEER  Model: DVD-ROM DVD-303  Rev: 1.10
  Type:   CD-ROM                   ANSI SCSI revision: 02
Host: scsi1 Channel: 00 Id: 06 Lun: 00
  Vendor: YAMAHA   Model: CRW4416S         Rev: 1.0g
  Type:   CD-ROM                   ANSI SCSI revision: 02

$ cat /proc/scsi/sg/device_strs 
IBM             DNES-309170W            SA30
PIONEER         DVD-ROM DVD-303         1.10
YAMAHA          CRW4416S                1.0g

$ echo "scsi remove-single-device 1 0 2 0" > /proc/scsi/scsi

$ cat /proc/scsi/scsi 
Attached devices: 
Host: scsi0 Channel: 00 Id: 00 Lun: 00
  Vendor: IBM      Model: DNES-309170W     Rev: SA30
  Type:   Direct-Access            ANSI SCSI revision: 03
Host: scsi1 Channel: 00 Id: 06 Lun: 00
  Vendor: YAMAHA   Model: CRW4416S         Rev: 1.0g
  Type:   CD-ROM                   ANSI SCSI revision: 02

$ cat /proc/scsi/sg/device_strs 
IBM             DNES-309170W            SA30
<no active device>
YAMAHA          CRW4416S                1.0g
注意 sg 驱动程序如何在 "device_strs" 输出中维护剩余设备的行位置。因此,当 Pioneer DVD 播放器被移除时,sg 设备映射中会出现一个空洞,但这不会反映在 cat /proc/scsi/scsi 输出中。那个“空洞”对应于设备名称/dev/sg1.

新的 sg_io_hdr 接口包含一个名为 "resid" 的数据传输残留计数字段。只有一些底层适配器支持此功能,而不支持此功能的适配器在此字段中始终产生零。在编写本文时,advansys、aha152x 和 sym53c8xx 驱动程序支持此功能。

9.4.1. sg 启动参数

sg 驱动程序为每个打开的文件描述符维护一个保留缓冲区。目的是保证应用程序的数据传输量不超过保留缓冲区的大小时,不会因缺少内核内存而失败。这对于像 cdrecord 这样的应用程序非常重要,因为它们无法轻易从 ENOMEM 错误中恢复(CDR)。

在没有引导参数 'sg_def_reserved_size' 或 sg 模块参数 'def_reserved_size' 的情况下,那么每次打开 sg 文件描述符时,保留缓冲区大小都从 SG_DEF_RESERVED_SIZE 继承,它在include/linux/sg.h.

SG_DEF_RESERVED_SIZE 定义值可以通过此内核引导选项覆盖

    sg_def_reserved_size=<n>

9.4.2. sg 模块参数

当加载 sg 模块时,SG_DEF_RESERVED_SIZE 定义值可以通过提供此选项来覆盖

    def_reserved_size=<n>

9.4.3. sg proc 接口

以下所有文件都可由所有人读取,并在读取时生成 ASCII 输出。文件 'def_reserved_size' 也可由 root 用户写入。ASCII 输出的格式使其既可供人类阅读,也可供机器读取(因此是一种折衷方案)。使用 cat device_hdrs devices 形式的 Unix 命令查看表的输出。

/proc/scsi/sg/debug       [internal state of sg driver]
/proc/scsi/sg/def_reserved_size
                          [like boot/module load parameter]
/proc/scsi/sg/devices     [table of numeric device data]
/proc/scsi/sg/device_hdr  [column headers for sg/devices]
/proc/scsi/sg/device_strs [table of strings from INQUIRY]
/proc/scsi/sg/hosts       [table of numeric host data]
/proc/scsi/sg/host_hdr    [column headers for sg/hosts]
/proc/scsi/sg/host_strs   [table of string ids for hosts]
/proc/scsi/sg/version     [sg version number and date]
以上所有文件都归 root 所有,并且可由所有人读取,而def_reserved_size可由 root 用户写入。对于devicesdevice_strs文件,第一行输出对应于/dev/sg0(sg 次设备号 0)。第二行输出对应于/dev/sg1, 等等。对于hostshost_strs文件,第一行输出对应于主机(适配器号)0,等等。对于数字表,缺失的设备或主机用一行 "-1" 值表示。对于字符串表,缺失的设备或主机用包含 "<no active device/host>" 的行表示。