筛选器驱动程序的 BypassIO
关于 BypassIO
BypassIO 功能为读取文件提供了优化的 I/O 路径。 该路径的目标是减少执行读取的 CPU 开销,这有助于满足在 Windows 上加载和运行下一代游戏的 I/O 需求。 BypassIO 是支持 Windows 上 DirectStorage 的基础结构的一部分。 它从 Windows 11 开始提供。
微型筛选器必须支持 BypassIO,并尽可能启用 BypassIO。 如果没有筛选器支持,游戏性能会下降,从而导致最终用户的游戏体验不佳。
将来的 Windows 版本中,除了游戏之外,还有更广泛的应用程序使用场景。
BypassIO 是每个句柄的概念。 在请求 BypassIO 时,它用于显式文件句柄。 BypassIO 对该文件的其他句柄并无影响。
作为此基础结构的一部分添加了 FSCTL_MANAGE_BYPASS_IO 和等效的 IOCTL_STORAGE_MANAGE_BYPASS_IO。 微型筛选器处理 FSCTL_MANAGE_BYPASS_IO,而 IOCTL_STORAGE_MANAGE_BYPASS_IO 则由文件系统发送到卷/存储堆栈。 根据设计,这些控制代码可诊断:它们都返回导致 BypassIO 请求失败的驱动程序的标识,以及否决它的原因。
本页提供文件系统筛选器和存储堆栈的体系结构详细信息,以及如何在微型筛选器驱动程序中实现 BypassIO 的信息。 有关存储驱动程序专用的 BypassIO 信息,请参阅存储驱动程序的 BypassIO。
BypassIO 支持的范围
从 Windows 11 开始,支持 BypassIO,如下所示:
仅在 Windows 客户端系统上。 将在未来版本中将添加服务器系统支持。
仅在 NVMe 存储设备上。 将来的版本中将添加对其他存储技术的支持。
仅在 NTFS 文件系统上。 将来的版本中将添加对其他文件系统的支持。
仅支持非缓存读取。 将在未来版本中添加对非缓存写入的支持。
仅在文件上受支持(目录或卷句柄不支持)。
BypassIO 的工作原理
当在启用 BypassIO 的 FileHandle 上调用 NtReadFile 时,该操作通常不会流经传统的 I/O 堆栈,因为传统的 I/O 堆栈会遍历整个文件系统堆栈、卷堆栈和存储堆栈。 相反,操作直接从 I/O 管理器流向 (NTFS) 文件系统,然后流向磁盘 (classpnp) 驱动程序,最后流向 StorNVMe 驱动程序。 使用完全启用 BypassIO 的 FileHandle:
- 所有文件系统筛选器都会被跳过。
- 所有卷堆栈筛选器都会被跳过。
- 跳过磁盘驱动程序之上以及磁盘和 StorNVMe 驱动程序之间的所有存储堆栈筛选器和驱动程序。
在文件系统筛选器堆栈支持 BypassIO,但卷和/或存储堆栈不支持 BypassIO 的情况下:
- 读取 IO 可绕过筛选器堆栈。
- 读取 IO 仍通过卷和/或存储堆栈来发送。
此支持级别被称为部分 BypassIO。
BypassIO 的 DDI 更改和新增内容
添加了以下与筛选器驱动程序相关的 DDI,以提供 BypassIO 支持:
- FltVetoBypassIo 函数
- FS_BPIO_INFLAGS 枚举器
- FS_BPIO_INFO 结构
- FS_BPIO_INPUT 结构
- FS_BPIO_OPERATIONS 枚举器
- FS_BPIO_OUTFLAGS 枚举器
- FS_BPIO_OUTPUT 结构
- FS_BPIO_RESULTS 结构
- FSCTL_MANAGE_BYPASS_IO 控制代码
- FsRtlGetBypassIoOpenCount 函数
此外,还更改了以下 DDI 以支持 BypassIO:
- 在 FSRTL_ADVANCED_FCB_HEADER 结构中添加了 BypassIoOpenCount 字段。 文件系统使用此字段来维护当前已启用 BypassIO 的流上唯一 FileObject 的计数。 增加这个字段会增大结构大小。 从 Windows 11 开始使用的结构版本是 FSRTL_FCB_HEADER_V4。
其他操作对启用 BypassIO 的句柄的影响
在句柄上启用 BypassIO 不会对其他句柄造成影响。 但是,对启用 BypassIO 的句柄进行的其他操作确实会影响 BypassIO 的使用,例如以下情况:
如果句柄 A 开启了 BypassIO 并在其上运行的文件,而某人(例如另一个线程或进程)打开了句柄 B 以执行缓存或内存映射 IO,那么句柄 A 上的 BypassIO 将被暂时中止,直到句柄 B 关闭为止。 系统会改为使用传统的 I/O 路径,以确保不会出现过时的数据。 系统将继续在该句柄上使用传统的 I/O 路径,直到所有数据段和缓存映射均被删除。 因此,筛选器必须在 BypassIO 恢复之前关闭句柄文件。
如果启用 BypassIO 的文件被标记为稀疏,所有 BypassIO 操作都将使用传统 I/O 路径启动。
删除启用 BypassIO 的文件会导致所有 BypassIO 操作都使用传统 I/O 路径。 一旦完成解码,系统就会切换回该句柄上的 BypassIO 路径。
在微型筛选器中实现 BypassIO 支持
更新 INF 或 MANIFEST 文件
从 Windows 11 开始,筛选器开发人员应在驱动程序的 INF 或 MANIFEST 文件中将 SUPPORTED_FS_FEATURES_BYPASS_IO 添加到 SupportedFeatures 中。 (可以在提升命令提示符下键入 fltmc instances
,以便查看所有活动筛选器的“SprtFtrs”值。)
注意
永远无法支持 BypassIO 的筛选器仍应在其 SupportedFeatures 状态中添加 SUPPORTED_FS_FEATURES_BYPASS_IO,然后在筛选器内部进行适当的否决并说明原因。
鼓励微型筛选器尽可能减少对 BypassIO 的否决。
如果微型筛选器连接到已启用 BypassIO 的卷,但该微型筛选器尚未更新其 SupportedFeatures 设置以包括 SUPPORTED_FS_FEATURES_BYPASS_IO,则该卷上的所有 BypassIO 操作将立即被阻止,退回到传统 I/O 路径,从而导致游戏性能下降。
不筛选 IRP_MJ_READ 或 IRP_MJ_WRITE 的微型筛选器将自动选择加入 BypassIO 支持,就像它们在 SupportedFeatures 中添加了 SUPPORTED_FS_FEATURES_BYPASS_IO 一样。
如果堆栈中附加的微型筛选器没有选择加入,则 FS_BPIO_OP_ENABLE 和 FS_BPIO_OP_QUERY 操作将失败。
实现对 BypassIO 请求的支持
微型筛选器应添加对 BypassIO 请求的支持,这些请求通过 FSCTL_MANAGE_BYPASS_IO 控制代码来发送。 有关详细信息,请参阅支持 BypassIO 操作。
确定 BypassIO 是否正常工作
新增的 fsutil 命令会发出 FSCTL_MANAGE_BYPASS_IO,从而指定 FS_BPIO_OP_QUERY 操作。 显示的结果可确定阻止 BypassIO 的第一个驱动程序及其原因。
> fsutil bypassIo state /v <path>
其中 <path> 可以是卷名称、目录名称或特定文件名,而 /v 是可选的详细标记。
在第一个示例中,假设 WOF 微型筛选器没有选择 BypassIO。 执行命令 fsutil bypassIo state c:\
的输出结果如下:
BypassIo on "c:\" is not currently supported.
Status: 506 (At least one minifilter does not support bypass IO)
Driver: wof.sys
Reason: The specified minifilter does not support bypass IO.
在第二个示例中,在启用了 BitLocker 的系统上执行 fsutil bypassIO state /v c:\
会得到以下输出结果:
BypassIo on "c:\" is partially supported
Volume stack bypass is disabled (fvevol.sys)
Status: 495 (The specified operation is not supported while encryption is enabled on the target object)
Reason: BitLocker Drive Encryption is enabled.
Storage Type: NVMe
Storage Driver: BypassIo compatible
Driver Name: stornvme.sys
特定于 NTFS 的行为
可以在 NTFS 驻留文件上启用 BypassIO;但是,只要是驻留文件,就会使用传统的 I/O 路径。 如果文件被写入,使其成为非驻留文件,系统就会切换到使用 BypassIO 路径。
无法在 BypassIO 活动文件上启用 NTFS 压缩。
可在 BypassIO 活动文件上启用 NTFS 加密。 BypassIO 会被暂停。
BypassIO 不影响卸载读/写操作。