既不使用缓冲 I/O,也不使用直接 I/O
如果驱动程序既不使用缓冲 I/O,也未使用直接 I/O,则 I/O 管理器会将其发送到驱动程序的 IRP 中传递原始用户空间虚拟地址。 若要安全地访问这些缓冲区,驱动程序必须在调用线程的上下文中执行。 因此,通常只有最高级别驱动程序(如 FSD)才能使用此方法访问缓冲区。
中间或最低级别驱动程序不能始终满足此条件。 例如,如果请求线程等待 I/O 请求完成,或者较高级别的驱动程序在中间或最低级别的驱动程序上分层,则不太可能在请求线程的上下文中调用较低级别的驱动程序的例程。
I/O 管理器确定 I/O 操作既不使用缓冲 I/O,也不使用直接 I/O,如下所示:
对于 IRP_MJ_READ 和 IRP_MJ_WRITE 请求,DEVICE_OBJECT 结构的 Flags 成员中既不设置 DO_BUFFERED_IO也不设置DO_DIRECT_IO 。 有关详细信息,请参阅 初始化设备对象。
对于 IRP_MJ_DEVICE_CONTROL 和 IRP_MJ_INTERNAL_DEVICE_CONTROL 请求,IOCTL 代码的值包含METHOD_NEITHER作为 IOCTL 值中的 TransferType 值。 有关详细信息,请参阅 定义 I/O 控制代码。
当驱动程序收到指定 I/O 操作的 IRP 时,既不使用缓冲 I/O,也不使用直接 I/O,它必须执行以下操作:
使用 ProbeForRead 和 ProbeForWrite 支持例程检查用户缓冲区地址范围的有效性,检查是否允许适当的读取或写入访问。 驱动程序必须将其对缓冲区地址范围的访问包含在驱动程序提供的异常处理程序中,以便用户线程无法在驱动程序访问内存时更改缓冲区的访问权限。 如果探测引发异常,驱动程序应返回错误。 驱动程序必须在发出 I/O 请求的线程上下文中调用这些例程;因此,只有更高级别的驱动程序才能执行此任务。
通过以下方式之一管理缓冲区和内存操作:
实际上,驱动程序必须基于每个 IRP 选择是在调用线程的上下文中执行缓冲 I/O、直接 I/O 还是 I/O,并且它必须处理用户模式线程上下文中可能发生的任何异常。 驱动程序必须根据需要管理自己的用户缓冲区访问、双重缓冲操作和内存映射,而不是让 I/O 管理器处理驱动程序的这些操作。