第 12 章. sg 的异步用法

建议基于 sg 的同步应用程序使用新的 SG_IO ioctl() 命令。现有的应用程序(主要是同步的)可以继续使用仍然支持的旧的基于 sg_header 的接口。

异步用法允许多个 SCSI 命令排队到设备。如果设备支持命令队列,则可以获得主要的性能提升。即使设备不支持命令队列(或者暂时繁忙),在中级或主机驱动程序中排队命令也可以获得较小的性能提升(因为当设备空闲时,传输下一个命令的延迟会更低)。

异步用法通常从在 open() 上设置 O_NONBLOCK 标志开始 [或者之后通过使用 fcntl(fd, SETFD, old_flags | O_NONBLOCK) 系统调用]。当使用 POSIX 线程时,可以获得类似的效果而无需使用 O_NONBLOCK。然后可以遵循以下几种策略

  1. 设置 O_NONBLOCK 并使用 poll() 循环

  2. 设置 O_NONBLOCK 并使用 SIGPOLL 信号在可读时提醒应用程序

  3. 使用 POSIX 线程和单个 sg 文件描述符

  4. 使用 POSIX 线程和多个 sg 文件描述符连接到同一设备

即使 SCSI 设备已被标记为离线,O_NONBLOCK 标志也允许 open()、write() 和 read() [但不包括 ioctl(SG_IO)] 访问该设备。当检测到 SCSI 设备并且它们没有按预期响应初始 SCSI 命令,或者在该设备上检测到某些 SCSI 错误情况并且中级错误恢复逻辑无法“复活”该设备时,SCSI 设备会被标记为离线。正在重置(并且仍在稳定)的 SCSI 设备可能在此期间通过使用 O_NONBLOCK 标志进行访问;这可能会导致意外行为,因此 sg 用户应注意。

在 Linux 中,SIGIO 和 SIGPOLL 是相同的信号。如果使用 POSIX 实时信号(例如,当 SA_SIGINFO 与 sigaction() 和 fcntl(fd, F_SETSIG, SIGRTMIN + <n>) 一起使用时),则与信号关联的文件描述符可供信号处理程序使用。关联的文件描述符位于 siginfo_t 结构的 si_fd 成员中。因此可以绕过信号接收后经常使用的 poll() 系统调用。