内存映射 IO 采用与直接 IO 不同的方法来消除普通(“间接”)IO 执行的额外数据复制。 使用 mmap 内存映射 IO,应用程序调用 mmap() 系统调用来内存映射 sg 的保留缓冲区。 sg 驱动程序为每个文件描述符维护一个保留缓冲区。 保留缓冲区的默认大小为 32 KB,可以使用 ioctl(SG_SET_RESERVED_SIZE) 进行更改。 mmap() 系统调用只需要在执行 mmap 内存映射 IO 之前调用一次[1]。 有关 mmap() 的更多详细信息,请参阅第 7.6 节。 应用程序通过在 'flags' 中设置 SG_FLAG_MMAP_IO 值来指示它想要在 SCSI 请求上使用 mmap 内存映射 IO。
由于每个 sg 文件描述符只有一个保留缓冲区,因此一次只能激活一个 mmap 内存映射 IO 命令。 为了使用 mmap 内存映射 IO 执行命令排队,应用程序需要打开多个文件描述符到同一个 SCSI 设备。 使用 mmap 内存映射 IO,各种状态值和 sense 缓冲区(如果需要)以与普通(“间接”)IO 相同的方式传回给应用程序。
Mmap 内存映射 IO 具有非常低的单命令延迟,因为保留缓冲区映射只需要为每个文件描述符执行一次。 此外,保留缓冲区由 sg 驱动程序设置,以帮助高效构建内部散列表,该散列表供较低级别(适配器)驱动程序用于 DMA 目的。 这往往比直接 IO 需要 sg 驱动程序处理成内部散列表的用户内存更有效。 因此,在这两个方面,mmap 内存映射 IO 都优于直接 IO。
[1] | 当 write() 或 ioctl(SG_IO) 尝试 mmap 内存映射 IO 时,不会检查之前是否已执行 mmap() 系统调用。 如果没有发出 mmap(),则随机数据被写入设备,或者从设备读取的数据是不可访问的。 此外,一旦在文件描述符上调用了 mmap(),则所有后续对 ioctl(SG_SET_RESERVED_SIZE) 的调用都将产生 EBUSY。 |