什么是File System Filter Driver?
文件系统过滤器驱动程序是一个可选驱动程序,可以为文件系统添加价值或修改文件系统的行为。 文件系统筛选器驱动程序是一个内核模式组件,作为 Microsoft Windows NT 执行程序的一部分运行。
文件系统过滤驱动程序可以过滤一个或多个文件系统或文件系统卷的 I/O 操作。 根据驱动程序的性质,过滤器可以意味着记录、观察、修改甚至阻止。 文件系统过滤器驱动程序的典型应用包括防病毒实用程序、加密程序和分层存储管理系统。
过滤器管理器概念
过滤器管理器随 Windows 一起安装,但仅在加载微过滤器驱动程序后才会激活。 过滤器管理器附加到目标卷的文件系统堆栈。 微筛选器驱动程序通过向筛选器管理器注册微筛选器驱动程序选择筛选的 I/O 操作,间接附加到文件系统堆栈。
旧筛选器驱动程序在文件系统 I/O 堆栈中相对于其他筛选器驱动程序的位置由其加载顺序组在系统启动时确定。 例如,防病毒筛选器驱动程序在堆栈中的位置应高于复制筛选器驱动程序,因此它可以在将文件复制到远程服务器之前检测病毒并对其进行杀毒。 因此,FSFilter 反病毒加载顺序组中的筛选器驱动程序将先于 FSFilter 复制组中的筛选器驱动程序加载。 每个加载顺序组都有一个相应的系统定义类和类 GUID,用于筛选器驱动程序的 INF 文件中。
与旧版筛选器驱动程序一样,微筛选器驱动程序按特定顺序附加。 然而,附着顺序是由称为海拔高度的唯一标识符确定的。 微过滤器驱动程序在特定卷上的特定高度的附加称为微过滤器驱动程序的实例。
微筛选器驱动程序的高度可确保微筛选器驱动程序的实例始终加载到相对于其他微筛选器驱动程序实例的适当位置,并且它确定筛选器管理器调用微筛选器驱动程序来处理 I/O 的顺序。 海拔高度由 Microsoft 分配和管理。
微筛选器驱动程序可以筛选基于 IRP 的 I/O 操作以及快速 I/O 和文件系统筛选器 (FSFilter) 回调操作。 对于它选择过滤的每个 I/O 操作,微过滤器驱动程序可以注册一个预操作回调例程、一个后操作回调例程或两者。 处理 I/O 操作时,筛选器管理器会为注册该操作的每个微筛选器驱动程序调用适当的回调例程。 当该回调例程返回时,筛选器管理器为注册该操作的下一个微筛选器驱动程序调用适当的回调例程。
例如,假设上图中的所有三个微过滤器驱动程序都注册了相同的 I/O 操作,过滤器管理器将按高度从最高到最低的顺序(A、B、C)调用它们的预操作回调例程,然后转发 I /O 请求下一级驱动程序进行进一步处理。 当筛选器管理器收到完成的 I/O 请求时,它以相反的顺序(从最低到最高(C、B、A))调用每个微筛选器驱动程序的操作后回调例程。
为了与遗留过滤器驱动程序进行互操作,过滤器管理器可以将过滤器设备对象附加到文件系统 I/O 堆栈的多个位置。 过滤器管理器的每个过滤器设备对象称为帧。 从遗留过滤器驱动程序的角度来看,每个过滤器管理器框架只是另一个遗留过滤器驱动程序。
每个过滤器管理器框架代表一个海拔范围。 过滤器管理器可以调整现有框架或创建新框架,以允许微型过滤器驱动程序连接到正确的位置。
过滤器管理器无法在两个附加的旧式过滤器之间附加微过滤器,除非它们之间已经存在过滤器管理器框架。 如果打算将微过滤器附加到旧式过滤器上方,则可以将其附加在旧式过滤器下方,具体取决于第二个附加旧式过滤器是否存在。 打算连接到旧过滤器下方的微过滤器可以连接到该旧过滤器上方。
重要 始终验证旧过滤器与微过滤器的互操作性,或考虑用微过滤器替换旧过滤器。 有关详细信息,请参阅移植旧版筛选器驱动程序的指南。
如果卸载并重新加载微过滤器驱动程序,则会在卸载时的同一框架中的相同高度处重新加载。
Windows I/O 模型概述
每个操作系统都有一个隐式或显式的 I/O 模型来处理进出外围设备的数据流。 Microsoft Windows I/O 模型的一项功能是支持异步 I/O。 此外,I/O模型还具有以下一般特征:
• I/O 管理器为所有内核模式驱动程序(包括最低级驱动程序、中间驱动程序和文件系统驱动程序)提供一致的接口。 所有对驱动程序的 I/O 请求都作为 I/O 请求数据包 (IRP) 发送。
• I/O 操作是分层的。 I/O 管理器导出 I/O 系统服务,用户模式受保护的子系统调用这些服务来代表其应用程序和/或最终用户执行 I/O 操作。 I/O 管理器拦截这些调用,设置一个或多个 IRP,并通过可能的分层驱动程序将它们路由到物理设备。
• I/O 管理器定义了驱动程序可以支持的一组标准例程,其中一些是必需的,另一些是可选的。 鉴于外围设备之间的差异以及总线、功能、过滤器和文件系统驱动程序所需的不同功能,所有驱动程序都遵循相对一致的实现模型。
• 与操作系统本身一样,驱动程序也是基于对象的。 驱动程序、其设备和系统硬件都表示为对象。 I/O 管理器和其他操作系统组件导出内核模式支持例程,驱动程序可以调用这些例程来通过操作适当的对象来完成工作。
除了使用 IRP 传送传统的 I/O 请求之外,I/O 管理器还与 PnP 和电源管理器一起发送包含 PnP 和电源请求的 IRP。
过滤 IRP 和快速 I/O
文件系统过滤器驱动程序过滤一个或多个文件系统或文件系统卷的I/O请求。 每个 I/O 请求均显示为 I/O 请求数据包 (IRP) 或快速 I/O 请求。 IRP 是由驱动程序的 IRP 调度例程处理的 I/O 系统结构。 快速 I/O 请求由驱动程序的快速 I/O 回调例程处理。
当过滤器驱动程序初始化时,其 DriverEntry 例程会注册过滤器驱动程序的 IRP 调度例程和快速 I/O 回调例程。 每个过滤器驱动程序只能注册一组这些例程。
某些类型的 IRP 具有快速 I/O 等效项,某些快速 I/O 请求也具有 IRP 等效项。 然而,IRP 可以处理快速 I/O 无法处理的许多类型的 I/O。 此外,某些专门的快速 I/O 例程用于为高速缓存管理器或内存管理器预先获取文件系统资源,而无需创建 IRP。 因此,在大多数情况下,IRP 和快速 I/O 请求在 I/O 操作中扮演不同的角色。
IRP 主要功能代码
每个 IRP 的每个驱动程序特定的 I/O 堆栈位置 (IO_STACK_LOCATION) 都包含一个主函数代码 (IRP_MJ_XXX),它告诉驱动程序它或底层设备驱动程序应该执行什么操作来满足 I/O 请求。 每个内核模式驱动程序必须为其必须支持的主要功能代码提供调度例程。
驱动程序对给定 IRP_MJ_XXX 代码执行的具体操作在一定程度上取决于底层设备,特别是对于 IRP_MJ_DEVICE_CONTROL 和 IRP_MJ_INTERNAL_DEVICE_CONTROL 请求。 例如,发送到键盘驱动程序的请求必然与发送到磁盘驱动程序的请求有所不同。 然而,I/O管理器为每个系统定义的主要功能代码定义了参数和I/O堆栈位置内容。
每个较高级别的驱动程序必须在 IRP 中为下一个较低级别的驱动程序设置适当的 I/O 堆栈位置,并使用每个输入 IRP 或使用驱动程序创建的 IRP(如果较高级别的驱动程序保留 到输入 IRP)。 因此,每个中间驱动程序必须为底层设备驱动程序处理的每个主要功能代码提供一个调度例程。 否则,只要应用程序或更高级别的驱动程序尝试向底层设备驱动程序发送 I/O 请求,新的中间驱动程序就会“破坏链”。
文件系统驱动程序还处理系统定义的 IRP_MJ_XXX 功能代码所需的子集,其中一些具有从属 IRP_MN_XXX 功能代码。
驱动程序处理使用以下部分或全部主要功能代码设置的 IRP:
IRP_MJ_CLEANUP
IRP_MJ_CLOSE
IRP_MJ_CREATE
IRP_MJ_DEVICE_CONTROL
IRP_MJ_FILE_SYSTEM_CONTROL
IRP_MJ_FLUSH_BUFFERS
IRP_MJ_INTERNAL_DEVICE_CONTROL
IRP_MJ_PNP
IRP_MJ_POWER
IRP_MJ_QUERY_INFORMATION
IRP_MJ_READ
IRP_MJ_SET_INFORMATION
IRP_MJ_SHUTDOWN
IRP_MJ_SYSTEM_CONTROL
IRP_MJ_WRITE
本节中描述的输入和输出参数是 IRP 中特定于函数的参数。