概述

Minifilter即File System Minifilter Drivers,是Windows为了简化第三方开发人员开发文件过滤驱动而提供的一套框架,这个框架依赖于一个称之为Filter Manager(后面简写为FltMgr)的传统文件系统过滤驱动。这套框架应用到内核中的结构如下图所示:

FltMgr以传统文件过滤驱动的形式插入到I/O处理队列中去接收不同的I/O请求,然后将这个请求遍历发布到它所维护的Minifilter对象中,然后根据各个Minifilter对这个I/O请求的处理结果来决定后续的操作。

这种模式在很多软件架构中使用,类似于插件一样,每一个Minifilter遵守一定的接口规范插入到FltMgr中,然后就能执行过滤控制。

上面是对整个Minifilter框架进行描述,实际内部需要注意的细节牵涉到很多内核知识,比如中断级别、I/O请求被封装成IRP包和fast I/O请求等相对复杂的概念。这里不做深究,主要以研究Minifilter的开发过程和相应注意的地方为主。此外还有FltMgr在内核中的位置等相关知识,也只在必要的地方提及一下。

Minifilter流程

Minifilter通过注册并启动后,根据在注册表中设置的相应值,插入到对应的FltMgr实例(Frame)队列中,然后关联上需要过滤的卷。FltMgr会根据Minifilter所注册的I/O操作类型,调用对应的pre和post操作函数,并根据对应的返回值执行不同的流程。这里假设有A、B、C三个Minifilter从上往下挂载在FltMgr实例上,那么当接收到I/O请求时,执行的步骤为A-pre、B-pre、C-pre,一旦某个Minifilter返回了FLT_PREOP_COMPLETE,即表明这个I/O请求被它完成处理了,则立即按照相反的顺序调用对应的post函数(不再继续往下调)。

注册和关联

Minifilter根据FltRegisterFilter函数介绍说明,为响应操作设置对应的回调函数和数据结构后,就可以在DriverEntry中调用FltRegisterFilter进行注册了,然后调用FltStartFiltering来通知FltMgr当前Minifilter已经准备好关联到要过滤的卷了。

FltMgr会在系统启动时或者接收到手动关联命令时,调用Minifilter的InstanceSetupCallback回调函数,当然前提是Minifilter在注册的时候增设置了这个函数的地址,这个回调函数会传入要关联的卷标信息,FltMgr会根据这个函数的返回值判断是否关联成功。这里和对应卷相关联的Minifilter实例叫做instance。一个卷上可以挂多个instance。只有对指定卷进行关联后,才能过滤其I/O请求。

取消关联的过程可以理解成释放实例的过程,释放后就无法继续过滤对应卷了。

Pre回调函数(PFLT_PRE_OPERATION_CALLBACK)

FLT_PREOP_COMPLETE:表示当前的过滤驱动完成了本次I/O操作,过滤管理器就不再往下发送本次I/O请求,而是依次向上调用post回调函数。这种情况下IoStatus.Status的值就是最终I/O操作的执行结果(不能是STATUS_PENDING)。

FLT_PREOP_SUCCESS_NO_CALLBACK/FLT_PREOP_SUCCESS_WITH_CALLBACK:这个返回值表示处理成功,让过滤管理器去做自己的事,区别在于WITH_CALLBACK的返回值会标明需要回调post函数。而NO_CALLBACK的则标明不需要。

FLT_PREOP_PENDING:顾名思义,表明当前过滤驱动将本次I/O操作挂起了,过滤管理器需要等待当前驱动调用FltCompletePendedPreOperation函数后才会继续本次I/0操作处理流程。注意只有对于基于IRP中断的I/O操作(用FLT_IS_IRP_OPERATION宏测试)才可以挂起。

FLT_PREOP_DISALLOW_FASTIO:只有操作是fast I/O操作(用FLT_IS_FASTIO_OPERATION(Data)进行测试)时才可以返回这个值,表明过滤驱动不允许fast I/O操作继续执行。因此过滤管理器不会再下发该请求,而是依次向上调用post回调函数。这种情况下不需要设置IoStatus.Status的值,过滤管理器会自动设置这个值。

FLT_PREOP_SYNCHRONIZE:这个返回值表明处理未完成,保持当前过滤驱动上下文线程环境,交由过滤管理器继续下发后调用post回调函数后继续处理。也只对基于IRP中断的操作有效,并且必须有post函数,如果不是基于IRP中断的,就会和FLT_PREOP_SUCCESS_WITH_CALLBACK一样。注意:对于Create操作,不应该返回这个值,因为文件管理器已经为这个操作进行同步了。此外对于同步的读和写操作,如果返回这个值会严重影响驱动和系统性能。

如果在pre和post函数中更改了Data的内容,必须调用FltSetCallbackDataDirty函数(更改IoStatus除外)。

Post回调函数(PFLT_POST_OPERATION_CALLBACK)

这个回调函数执行的中断等级为IRQL <= DISPATCH_LEVEL。所以需要注意以下几点:1、不能安全调用必须低于IRQL级别的任何内核模式的派遣函数。2、在这个函数内开辟的任何数据结构必须位于非页内存。3、该函数不可分页。4、不能请求资源(resource)、信号量(mutextes)和快速信号量(fast mutexes),只能获取互斥锁(spin lock)。5、不能获取、设置或者删除上下文,但可以释放上下文。

相对于Pre回调函数多了最后一个参数Flags,这个参数如果存在FLTFL_POST_OPERATION_DRAINING标记位,则表明当前过滤驱动实例正在被取消关联,本次调用是为了清理pre回调函数传入的completion context,返回值必须是FLT_POSTOP_FINISHED_PROCESSING,并且这个回调是在IRQL<=APC_LEVEL执行的。

FLT_POSTOP_FINISHED_PROCESSING:表明本过滤驱动完成了对I/0操作的处理并将控制交还给过滤管理器。

FLT_POSTOP_MORE_PROCESSING_REQUIRED:只有当微过滤驱动将本次I/O操作发送到工作队列中时,才能返回这个值,微过滤驱动最后必须负责完成这个I/O操作。过滤管理器会继续等待FltCompletePendedPostOperation函数被调用后才继续执行控制。注意:这个返回值也必须对基于IRP中断的操作执行。

任何要被执行在IRQL<DISPATCH_LEVEL的I/O完成处理都不能在这个回调函数内直接执行。取而代之,可以使用FltDoCompletionRpocessingWhenSafe或者FltQueueDeferredIoWorkItem之类的函数发送到工作队列中。

除了以下情况外,要确保在Flags参数没有FLTFL_POST_OPERATION_DRAINING标记位的时候才能调用FltDoCompletionRpocessingWhenSafe函数:

1、如果微过滤驱动的pre回调函数为一个基于IRP中断的操作返回FLT_PREOP_SYNCHRONIZE,那么对应的post回调要保证和pre回调都处在IRQL<=APC_LEVEL的线程上下文中。

2、对于create操作的post回调要保证中断级别为IRQL_PASSIVE_LEVEL(原始IRP_MJ_CREATE操作所处的线程上下文)。

基于Minifilter框架的文件过滤驱动理解的更多相关文章

  1. 文件过滤驱动实现目录重定向(一)good

    文件过滤驱动拦截的IRP主要包括以下几个:IRP_MJ_CREATE,文件创建操作,文件的任何操作,都是从这里开始的.IRP_MJ_CLEANUP,文件的HANDLE句柄全部关闭会触发这个消息IRP_ ...

  2. [转载]文件过滤驱动 文件系统激活通知 IoRegisterFsRegistrationChange函数实现

    IoRegisterFsRegistrationChange 注册一个文件系统变动回调函数,用来被通知文件系统的激活和注销,激活是指第一次加载文件系统,当一个文件系统已经加载后,当加载一个同种文件系统 ...

  3. Windows 文件过滤驱动经验总结

    Windows 文件过滤驱动经验总结作者:sinister 本文转载自驱动开发网 看了 ChuKuangRen 的第二版<文件过滤驱动开发教程>后,颇有感触.我想,交流都是建立在平等的基础 ...

  4. 文件过滤驱动框架Minispy解析一

    因工作需要,研究minispy文件过滤框架,上图为我整理出的其内核部分代码的逻辑.

  5. Struts2内建校验器(基于校验框架的文件校验)

    位于xwork-2.0.4.jar压缩包中( com.opensymphony.xwork2.validator.validators)有个文件default.xml ,该文件中定义了Struts2框 ...

  6. 【转】NodeJS教程--基于ExpressJS框架的文件上传

    本文是翻译的一篇文章,原文地址:Handle File Uploads in Express (Node.js). 在NodeJS发展早期上传文件是一个较难操作的功能,随后出现了formidable. ...

  7. 基于SSM框架的文件上传

    我整理了一下,这个办法在Servlet上应该也用得上.其实文件上传主要的问题是在于存储路径的拼接. 这里我是把东西存在Web项目的WebContent目录下的 下面贴一些代码 目标应该是这样一个格式 ...

  8. File System Minifilter Drivers(文件系统微型过滤驱动)入门

    问题: 公司之前有一套文件过滤驱动,但是在实施过程中经常出现问题,现在交由我维护.于是在边看代码的过程中,一边查看官方资料,进行整理. 这套文件过滤驱动的目的只要是根据应用层下发的策略来控制对某些特定 ...

  9. 驱动开发:内核枚举Minifilter微过滤驱动

    Minifilter 是一种文件过滤驱动,该驱动简称为微过滤驱动,相对于传统的sfilter文件过滤驱动来说,微过滤驱动编写时更简单,其不需要考虑底层RIP如何派发且无需要考虑兼容性问题,微过滤驱动使 ...

随机推荐

  1. 从零开始,在windows上用nodejs搭建一个静态文件服务器

    从零开始,在windows上用nodejs搭建一个静态文件服务器 首先安装nodejs: 新建一个node文件夹 下载node.exe到该文件夹 下载npm然后解压到该文件夹 现在node文件夹是这样 ...

  2. JS遍历对象或者数组

    一.纯js实现 <script> var obj = {"player_id":"GS001","event_id":" ...

  3. SpringMVC介绍之约定优于配置

    SpringMVC介绍之约定优于配置 所谓的约定优于配置就是指在程序开发过程中我们约定好一些规则可以使我们更少的进行配置和代码编写.就这么简单的一句话可能你还不是很懂什么是约定优于配置,没关系,看完后 ...

  4. 正确设置网站title、keywords、description(转载)

    本文转载自蚂蚁HR(www.mayihr.com) 优化技巧是老师在课堂上教不了你的,而自己也不可能在练习中领悟,最便捷的方法就是听取别人的经验,所以转载一下 1.title(网站标题) title, ...

  5. jQuery键盘控制方法,以及键值(keycode)对照表

    键盘控制应用范围非常广泛,比如快捷键控制页面的滚动:在填写表单时候,限制输入内容:或者是屏蔽复制.粘贴.退后等功能.这里说说用jQuery怎么来实现.个人觉得jQuery比原生态的JS好用,代码简单清 ...

  6. 数据类型和Json格式[转]

    1. 前几天,我才知道有一种简化的数据交换格式,叫做yaml. 我翻了一遍它的文档,看懂的地方不多,但是有一句话令我茅塞顿开. 它说,从结构上看,所有的数据(data)最终都可以分解成三种类型: 第一 ...

  7. php面向对象编程--学习笔记

    1.声明一个类 在php中使用class关键字创建一个新类,类包括属性与方法.语法格式如下: <?php class类名{ 属性: 方法: } ?> 2.创建一个实例对象 创建对象的过程称 ...

  8. Hadoop-CDH5.7.0 for CentOS7

    一.需求 系统 CentOS 7 最小化安装 JDK环境 JDK版本:1.8.0_91 jdk-8u91-linux-x64.rpm 下载地址:http://www.oracle.com/techne ...

  9. 素数判定 AC 杭电

    素数判定 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submi ...

  10. 通过Web Deploy方式部署WCF

    如何发布WCF, 其实它有很多种方式去发布WCF服务到IIS上,这篇文章将介绍通过Web Deploy的发布方式去部署. 步骤: 在IIS上创建一个网站 打开IIS, 右击“Site” -> & ...