具体实施方式
示范操作环境
图1展示了可以在其上执行本发明的合适的计算系统环境的一个例子。计算系统环境100只是合适的计算环境的一个例子,并不意在对本发明的使用或功能性的范围提出任何限制。也不应该将计算环境100解释为具有涉及示范操作环境100中所展示的任何一个部件或部件组合的任何从属性或要求。
本发明可用于许多其他通用或专用的计算系统环境或配置。可能适用于本发明的众所周知的计算系统、环境和/或配置的例子包括(但不局限于)个人计算机、服务器计算机、手持或便携式设备、输入板设备、多处理器系统、基于微处理器的系统、置顶盒、可编程消费电子设备、网络PCs、小型计算机、大型计算机、包括以上任何系统或设备的分布式计算环境以及类似的例子。
可以在计算机正在执行的计算机可执行指令(例如,程序模块)的一般上下文中描述本发明。通常,程序模块包括执行特殊任务或实施特殊的抽象数据类型的例行程序、程序、对象、部件、数据结构等。本发明也可以在分布式计算环境中被加以实践,在这些分布式计算环境中,由通过通信网络而被连接的远程处理设备来执行任务。在分布式计算环境中,程序模块可以位于包括记忆存储设备的本地计算机存储介质和远程计算机存储介质中。
参照图1,用于执行本发明的示范系统包括采取计算机110形式的通用计算设备。计算机110的部件可以包括(但不局限于)处理单元120、系统存储器130以及将包括该系统存储器的各种系统部件耦合到处理单元120的系统总线121。系统总线121可以是几种类型的总线结构(包括存储总线或存储控制器、外围总线和使用各种总线构造中的任何总线构造的局域总线)中的任何总线结构。举例来讲(不作限制),这类构造包括“工业标准结构”(ISA)总线、“微通道结构”(MCA)总线、“增强型ISA”(EISA)总线、“视频电子标准协会”(VESA)局域总线和也被称作“中层楼(Mezzanine)总线”的“外围部件互连”(PCI)总线。
计算机110通常包括各种计算机可读介质。计算机可读介质可以是可由计算机110存取的任何可用的介质,并且包括易失和非易失介质、可移动和不可移动介质。举例来讲(不作限制),计算机可读介质可以包括计算机存储介质和通信介质。计算机存储介质包括易失和非易失的可移动和不可移动介质,它们用信息(例如,计算机可读指令、数据结构、程序模块或其他数据)存储的任何方法或技术来加以执行。计算机存储介质包括(但不局限于)RAM、ROM、EEPROM、快闪存储器或其他存储技术、CD-ROM、数字通用磁盘(DVD)或其他光盘存储器、盒式磁带、磁带、磁盘存储器或其他磁性存储设备、或可以被用来存储所需信息并可以由计算机110来进行存取的任何其他介质。通信介质通常具体表现计算机可读指令、数据结构、程序模块或调制数据信号(例如,载波或其他传送机制)中的其他数据,并且包括任何信息传递介质。术语“调制数据信号”意味着一种信号,该信号的一个或多个特征用这样一种方式来加以设置或改变,以便为该信号中的信息编码。举例来讲(不作限制),通信介质包括有线介质(例如,有线网络或直线连接)和无线介质(例如,声音、RF、红外线和其他无线介质)。以上任何内容的组合也应该被包括在计算机可读介质的范围以内。
系统存储器130包括采取易失和/或非易失存储器(例如,只读存储器(ROM)131和随机存取存储器(RAM)132)形式的计算机存储介质。基本输入/输出系统133(BIOS)通常被存储在ROM 131中,该基本输入/输出系统包含有助于在计算机110内的各个元件之间传送信息(例如,在启动期间)的基本例行程序。RAM 132通常包含处理单元120可立即存取并且/或者目前正在操作的数据和/或程序模块。举例来讲(不作限制),图1展示了操作系统134、文件系统135、应用程序136、其他程序模块137和程序数据138。
计算机110也可以包括其他可移动/不可移动的易失/非易失计算机存储介质。仅通过举例,图1展示了从不可移动的非易失磁性介质读取或对其写入的硬盘驱动器141、从可移动的非易失磁盘152读取或对其写入的磁盘驱动器151以及从可移动的非易失光盘156(例如,CD ROM或其他光学介质)读取或对其写入的光盘驱动器155。可以被用于示范操作环境中的其他可移动/不可移动的易失/非易失计算机存储介质包括(但不局限于)盒式磁带、快闪存储卡、数字通用磁盘、数字录像磁带、固态RAM、固态ROM和类似的存储介质。硬盘驱动器141通常通过不可移动的存储接口(例如,接口140)被连接到系统总线121,磁盘驱动器151和光盘驱动器155通常由可移动的存储接口(例如,接口150)连接到系统总线121。
以上所讨论的和图1中所展示的各种驱动器及其关联的计算机存储介质为计算机110提供计算机可读指令、数据结构、程序模块和其他数据的存储。在图1中,例如,将硬盘驱动器141示作存储操作系统144、应用程序145、其他程序模块146和程序数据147。注意,这些部件可以等同于或不同于操作系统134、应用程序136、其他程序模块137和程序数据138。这里为操作系统144、应用程序145、其他程序模块146和程序数据147提供不同的号码,以展示它们至少是不同的副本。用户可以通过输入设备(例如,输入板(电子数字转换器)164、话筒163、键盘162)和定点设备161(通常被称作“鼠标”、“跟踪球”或“触垫”),将命令和信息输入计算机110。其他输入设备(未示出)可以包括操纵杆、游戏垫、圆盘式卫星电视天线、扫描仪或类似的输入设备。这些和其他的输入设备经常通过被耦合到系统总线的用户输入接口160而被连接到处理单元120,但也可以由其他接口和总线结构(例如,并行端口、游戏端口或通用串行总线(USB))来连接。监视器191或其他类型的显示设备也经由接口(例如,视频接口190)被连接到系统总线121。监视器191也可以与触屏屏面或类似物相结合。注意,该监视器和/或触屏屏面可以在物理上被耦合到其中并入计算设备110的外壳(例如,在输入板类型的个人计算机中)。此外,计算机(例如,计算设备110)也可以包括诸如扬声器195和打印机196的其他外围输出设备,这些外围输出设备可以通过输出外围接口194或类似的接口而被连接。
计算机110可以在使用与一台或多台远程计算机(例如,远程计算机180)的逻辑连接的联网环境中进行操作。远程计算机180可以是个人计算机、服务器、路由器、网络PC、对等设备或其他共同的网络节点,它通常包括以上相对于计算机110所描述的许多或全部元件,尽管图1中只展示了记忆存储设备181。图1中所描绘的各种逻辑连接包括局域网(LAN)171和广域网(WAN)173,但也可以包括其他网络。这类联网环境在办公室、企业范围的计算机网络、内联网和因特网中很普遍。例如,在本发明中,计算机系统110可以包括正从那里迁移数据的源机器,远程计算机180可以包括目标机器。但是,注意,源机器和目标机器不需要由网络或任何其他的方法来连接,相反,可以经由能够由源平台写入并由一个或多个目标平台读取的任何介质来迁移数据。
当被用于LAN联网环境中时,计算机110通过网络接口或适配器170被连接到LAN 171。当被用于WAN联网环境中时,计算机110通常包括调制解调器172或用于在WAN 173(例如,因特网)上建立通信的其他装置。调制解调器172(可能是内置的,也可能是外置的)可以经由用户输入接口160或其他合适的机制被连接到系统总线121。在联网环境中,相对于计算机110所描绘的程序模块或其各个部分可以被存储在远程记忆存储设备中。举例来讲(不作限制),图1将远程应用程序185示作驻留在存储设备181上。将会理解,所示的网络连接起示范的作用,并可以使用在各台计算机之间建立通信路线的其他方法。
被管理的文件系统过滤器模型和构造
本发明一般针对一种文件系统过滤器模型和构造,该文件系统过滤器模型和构造意在改进过滤器的文件系统I/O处理,包括通过促进各种有关文件系统的产品之中的互用性。注意,这里通常参照在I/O管理器与基文件系统(可以是本地文件系统或远程文件系统)之间进行操作的过滤器驱动器来描述该模型,而不是参照其他驱动器(包括在该文件系统与一个或多个存储驱动器(例如,FtDisk或DMIO)之间进行操作的过滤器驱动器)来描述该模型。
如这里所使用的,“传统”过滤器驱动器按传统方式而不是通过新的模型来处理I/O请求分组(IRPs),该新的模型如下所述使用到已登记的过滤器驱动器的回收。预期传统过滤器驱动器随着时间的推移将逐步被淘汰,因此,遵守新的登记和回收模型的过滤器驱动器将在这里被简单地称作“过滤器驱动器”。
新的过滤器模型的主要特征之一针对取消传统、复杂的I/O通过堆栈模型在各个传统过滤器之间传送,并用管理回收模型来取代那个模型,在该管理回收模型中,过滤器管理器将IRP、快速I/O路径、存储管理器回收等转变成将采用定义格式的回收数据提供给过滤器的回收。如下所述,这些过滤器没有调用其他过滤器,也没有将控制直接传给其他过滤器,而是按需要来操作回收数据,并响应于该回收来返回状态。由于过滤器不再必须处理IRP和类似物,因此,从过滤器中除去大部分的I/O处理复杂性,并将这大部分的I/O处理复杂性置入单一过滤器管理器,从而消除了由各种过滤器引起的许多问题。例如,IRP经常包含传统过滤器驱动器传统上一直难以处理的暗示的复杂信息;本发明通过让过滤器管理器处理该暗示信息并且只将明确的上下文传送给过滤器,解决了这个问题。回收模型还具有一个好处:解决了因链式IRP配送而出现的堆栈溢出和锁定问题。
图2表现新的模型的范例实施200。图2中所表现的实施的一个优点是:要执行这个新的模型,不需要以任何方式修改现存的应用程序、操作系统部件和文件系统。例如,在基于Windows的操作系统中,应用程序202将仍然继续通过API层204~I/O管理器206提出文件系统请求(例如,经由功能/方法调用)。已知:I/O管理器206生成IRP或其他类型的I/O,并将该I/O发送到(传统)过滤器驱动器堆栈208的顶部。如下所述,堆栈208中的部件之一是过滤器管理器212。
一般而言,过滤器管理器212将I/O(无论是IRP、快速I/O、FS过滤器回收,还是类似物)转变成被称作“回收数据”的统一结构。以下描述了一种合适的回收数据结构。然后,过滤器管理器212预排已登记的过滤器驱动器的清单(例如,图2中示出五个这样的过滤器驱动器282A-282E,尽管可能有任何实际数量的这类驱动器),并且可以为每个过滤器驱动器调用I/O的登记配送。重要的是,在本发明的模型中,过滤器不是接收和/或处理IRP,而是本质上指示过滤器管理器212如何利用I/O请求。
也如图2中所表现的,例如通过将传统过滤器驱动器210放置在堆栈210的顶部,这些传统过滤器驱动器在此项实施中仍然可以得到支持。但是,注意,可以按相对于其他堆栈部件的某种其他的顺序来对它们进行安排。例如,由于安排传统过滤器驱动器处理IRP而不是处理回收,因此,特殊的管理代码可以围绕这种传统过滤器,以便根据回收数据来生成IRP,从而传送给它,从它那里接收(可能是被修改的)IRP,并将其转换回状态响应。利用这种方式,可以在回收模型内插入并隔离传统过滤器。无论如何,仍然可以在新的模型中使用传统过滤器。
为了概述图2中所示的实施例,文件系统过滤器管理器212被用于新的模型中,并且被放入过滤器驱动器堆栈208(好象它是传统过滤器驱动器),以便它可以接收并处理IRP。注意,这样,允许过滤器管理器只在现存的I/O系统中运作,但是,不言而喻,可以提供相等的模型(例如,没有高级传统过滤器),在该模型中,更新的I/O管理器将I/O数据传送给除IRP数据结构以外的某物中的过滤器管理器。例如,当I/O管理器生成IRP时,过滤器驱动器根据IRP来生成回收数据结构,这样,可以更有效率地让I/O管理器直接生成回收数据结构。注意,已在现存的系统中为快速I/O、存储管理器回收等提供除IRP以外的某物,这是因为一些普通I/O任务(例如,读取/写入/设备I/O控制)的更快速的执行是基于回收,而不是基于分组。另外,注意,在现存的系统中,快速I/O仍然被传递通过堆栈(即链式),因此不象本发明的基于回收的模型。为简单起见,除另外特别指出外,本文将主要使用IRP的例子。
在一项实施中,过滤器驱动器包括当具有登记机制的例示(通常在其驱动器初始化程序期间)寄存器在过滤器管理器212中时的对象或类似物。为获取效率,这些过滤器驱动器通常将只为它们可能有兴趣处理的文件系统请求进行登记。为了达到这个目的,作为登记的一部分,每个过滤器驱动器向过滤器管理器通知其感兴趣的I/O请求类型(例如,创建、阅读、写入、关闭等)。例如,加密过滤器驱动器可以为阅读和写入IRP进行登记,但不会为其中不一定要为数据加密或解密的其他IRP进行登记。同样,定额过滤器可能只对文件创建和文件写入感兴趣。结果,该模型比栈式过滤器模型更有效率,这是因为过滤器驱动器只了解它们已为其进行登记的I/O。
为了允许附属于卷,本发明的模型定义了过滤器驱动器(和以下所述的卷上下文)的“实例”的概念。尤其是,当安装新的卷时,经由实例设置通知,来通知希望附属于卷的过滤器驱动器。为在装载过滤器驱动器之前已安装的卷提供类似的通知。然后,如下所述,过滤器驱动器可以经由登记来选择附属于卷;如果是这样,则使用实例对象来表现附属实例。当卷卸载时,同样通知过滤器驱动器,即通过实例分谴通知。本模型也虑及过滤器驱动器动态地离开安装的卷。
比如标题为《用于软件模块的确定性排序的方法和系统》的美国专利申请(序号为09/768,098)中通常描述:过滤器驱动器可能与一个高度有关联,该高度指出那个驱动器按回收顺序位于何处。而且,如图3中所表现的,过滤器驱动器可以多次附属于同一个卷,从而为每个附属创建实例(虽然如此,但是,无论是通过凭单编号还是通过某种取代机制,同一卷的每个实例一定位于不同的高度)。
图3表现了具有多个实例的范例过滤器。在图3中,过滤器A(例如,“文件系统活动监控”过滤器)监控文件I/O,并具有两个实例——过滤器A和过滤器A’。利用这种方式,文件活动监控产品能够(经由过滤器A)观察进入中间(例如,抗病毒)过滤器B的I/O,并且(经由过滤器A’)观察在朝向文件系统的过程中最终通过那个中间过滤器的I/O。例如,经由如下所述的消息,文件活动监控产品可以包括用户状态程序(未分开示出),过滤器A和过滤器A’向该用户状态程序报告。
这样,总卷过滤器驱动器实例可能与一个高度有关联,该高度确定那个卷的每个实例位于何处。高度可以被预先分配给所提供的过滤器实例(例如,在序号为09/768,098的美国专利申请中),并且/或者,(以下所描述的)标记机制或类似的机制可以被用来导出过滤器的合适的高度。例如,不应该允许抗病毒过滤器附属于加密过滤器与基文件系统之间,因为它在加密之前需要了解按现状的数据。标记可以指出过滤器是否检查数据(例如,抗病毒过滤器)、是否修改数据(例如,加密过滤器)等,从中可以导出高度。利用这种方式,回收顺序不是基于装载驱动器的顺序,而是基于某种预定的逻辑基础。
根据本发明的一个方面,过滤器驱动器登记两种回收,即前回收和后回收。在I/O往下(即朝向文件系统)的过程中调用前回收,同时,在从文件系统朝向I/O管理器的倒退过程中,在I/O的完成期间调用后回收。
为获取效率,要跟踪哪些过滤器驱动器已为哪些类型的回收进行登记,从而有效率地确定当接收I/O(例如,IRP)时调用哪些过滤器驱动器,过滤器管理器212保持一个或多个总卷数据结构。例如,如图4中所表现的,当过滤器实例在过滤器管理器212中的登记机制402(例如,通过调用功能)处进行登记时,该登记机制经由排序机制404来确定该过滤器实例按前回收顺序属于哪里。排序机制404可以基于高度的简单比较,或者可以包括逻辑,该逻辑评估标记,以确定过滤器实例适合在哪里。无论如何,都保持总卷回收节点,其中有登记信息。
如下所述,在登记中被发送到过滤器管理器的信息的一部分包括(例如,在一个阵列中)过滤器实例想要其前回收的文件系统请求的清单。使用该信息来编制总卷有序清单408(例如,卷c:)或410(例如,卷d:)或类似物,由此,过滤器管理器212中的回收机制412可以有效率地确定调用每个实例的顺序。例如,如图4中所表现的,如果接收关于c:卷上的文件的阅读请求,则可以迅速获得有兴趣阅读的过滤器实例(如IRP的IRP主要代码所指明),例如,过滤器实例A、过滤器实例B和过滤器实例A’将是前回收顺序,图4中的例子表现了这一点。注意,这非常有效率,并且也促进了动态登记;新的过滤器实例随时可进行登记,登记机制可以适当地重建这些清单。
利用这种方式,对于每一类型的文件I/O请求,可确定前回收顺序,尽管如下所述,由每个过滤器实例返回的状态可能会影响接收回收的实际过滤器实例(例如,过滤器会舍弃回收)。后回收本质上按相反的顺序运作,但是,如下所述,被调用的实例在前回收中会返回的状态值之一是没有后回收的成功,在这种情况下,过滤器管理器212将跳过那个实例的后回收。
过滤器实例可能会响应于回收而返回的状态值通常包括:没有回收的成功、有回收的成功、未决、同步、完成和不准许快速I/O。在一项特殊的实施中,如同状态“FLT_PREOP_SUCCESS_WITH_CALLBACK”那样,“FLT_PREOP_SUCCESS_NO_CALLBACK”继续处理I/O通过,当这个I/O完成时,这进一步请求完成回收。过滤器也可以指定FLT_PREOP_PENDING,它保持该I/O,直到过滤器以后调用FltCompletePendedPreOperation( )为止。FLT_PREOP_SYNCHRONIZE等候I/O完成,并且调用原来的线程上下文中的后回收。I/O同步由“过滤器管理器”进行处理。注意,不能利用快速I/O来返回“未决”和“同步”。FLT_PREOP_COMPLETE完成具有成功或失败状态码(通常类似于传统配送中的IoCompleteRequest)的I/O。FLT_PREOP_DISALLOW_FAST_IO只对“快速I/O”而言是有效的,并且通常等同于在传统配送中返回FALSE。
在这种方式中,管理过滤器驱动器模型允许过滤器驱动器经由来自其前回收例行程序的返回状态来控制I/O的执行路径。这允许过滤器驱动器请求处理I/O的不同的方法,包括待决、完成、传递给低级过滤器、请求后回收、请求“同步”后回收等。
如这里所描述的,过滤器实例为后回收进行登记。响应于后回收,过滤器实例(例如,以前返回FLT_PREOP_SUCCESS_WITH_CALLBACK的状态)可以返回FLT_POSTOP_FINISHED_PROCESSING的状态来继续I/O完成,或者可以返回FLT_POSTOP_MORE_PROCESSING_REQUIRED来放弃完成,并且以后通过调用FltCompletePendedPostOperation( )功能来完成I/O。过滤器可以经由再分析处理程序的FltReissueSynchronousIo( )功能调用,在其操作后处理期间重新发出I/O。为想要通过舍弃创建请求来阻止文件打开的过滤器提供FLT_POSTOP_UNDO_CREATE状态。
过滤器管理器212用一种方式来处理I/O完成,该方式保证其前回收中的过滤器实例所了解的参数与其后回收中的一样。注意,与传统栈式模型相比,这是一个改进,在传统栈式模型中,过滤器经常改变参数、缓冲指示字等,从而导致许多问题。一般而言,如图5中所表现的那样来执行这一点,其中,过滤器管理器为每个实例(即,至少为接收回收的那些实例)保持完成节点。
本质上,关于在已(经由其状态)请求回收的前回收中被调用的每个实例,过滤器管理器在每个前回收之前给参数拍快照,将该快照存储在完成节点中,并将完成节点推到堆栈502上。为了管理后回收数据,过滤器管理器为每个IRP保持IRPCTRL头部504(不被过滤器驱动器了解),IRPCTRL头部504跟踪的信息包括设备对象、IRP指针、节点信息(包括完成节点的尺寸及其对应的实例)等。然后,在后回收期间,过滤器管理器本质上向后运行,使每个完成节点突然离开堆栈504,并将完成节点数据置入那个实例的回收数据506,从而恢复其参数。注意,如果过滤器实例在按顺序被预先调用之前动态地进行登记,则可以利用增加的完成节点将该堆栈拷贝到另一个堆栈;如果在预先调用已按预先调用顺序来为给定的IRP传递它之后被进行登记,则那个实例将不会被收回。
为获取效率,当过滤器实例将要接收回收时,并且当过滤器实例改变回收数据时,堆栈只需要具有被推到该堆栈上的完成节点,因为否则可以再使用同一个完成节点。当过滤器实例修改数据时,它负责设置“弄脏”(dirtied)参数标记。注意,如果它不这样做,则将放弃其变化,并且将不会给其改变的数据拍快照,由此,另一个驱动器将不会了解任何变化。
返回到图2,在执行最后的后回收之后,通过任何高级传统过滤器210,过滤器管理器212将回收数据再转换(整理)成IRP,并朝向I/O管理器206沿堆栈返回该IRP。可以理解,通过利用这种管理过滤器模型,可以消除或大大减少传统模型的许多缺点。
除以上功能以外,过滤器管理器还提供了充足的API集,该API集提供过滤器通常所需要的各种功能。例如,某些过滤器需要执行自己的I/O(例如,抗病毒过滤器可能会希望在打开文件之前阅读该文件)。当过滤器驱动器希望启动其自己的I/O操作时,它首先调用FltAllocateCallbackData( )。这项功能定位并返回FLT_CALLBACK_DATA结构,然后,过滤器用任何有关的域来填充该结构。注意,FltAllocateCallbackData本质上是用于调用传统系统中的IoAllocateIrp( )的替换。当过滤器准备好将I/O请求发送到任何剩余的过滤器、传统过滤器和基文件系统时,它调用FltPerformSynchronousIo( )或FltPerformAsynchronousIo( )(类似于IoCallDriver( ))。默认的情况是,将过滤器启动的I/O发送到给定的卷的下一个附属过滤器,从而回避在启动I/O的过滤器以上所附属的任何过滤器。但是,如同分级存储器管理程序(HSM)过滤器可能需要做的那样,可以将I/O发送到系统中的任何设备。
另一个例子是,过滤器有时需要创建文件,FltCreateFile( )功能作为用于启动I/O的起点。这项功能所返回的句柄可以被用于采用文件句柄的现存操作系统APIs,并且,这项功能允许在其他实例上进行文件创建。该功能支持共享访问(share-access)取代。另外,过滤器管理器确保任何回收只被请求过滤器以下的过滤器(包括被动态插入的过滤器)了解,这避免了递归回收,可以理解这一点。为了达到这个目的,过滤器管理器利用实例提示来创建文件,并使用这个提示来识别请求过滤器。注意,固定点打开是一个例外,因为它们需要到回收堆栈的顶部。
FltReadFile( )允许利用将在I/O完成上被发出的过滤器供应回收,来进行同步和异步的I/O。FltWriteFile( )、FltSetInformationFile( )等具有类似的语义学。FltAllocateCallbackData( )允许对I/O进行定制,包括FltPerformSynchronousIo( )或接受I/O完成回收的FltPerformAsynchronousIo( )。
上下文管理是过滤器管理器供应APIs非常有益的另一个例子,因为过滤器经常需要使上下文结构跟每个流句柄、流、实例和卷相关联。例如,过滤器使用这些上下文来存储在过滤器截取I/O时被查找的每一句柄/每一流/每一文件/每一卷/每一实例信息。当过滤器(例如)经由API来请求那个过滤器已在实体上设置的任何上下文时,该上下文将被传递给该过滤器。上下文的使用期限由过滤器管理器212来进行管理,当因正在被删除的合适的对象(例如,流/文件/实例/卷)而删除上下文时,将收回过滤器。
根据本发明的另一个方面,过滤器管理器212提供有效率的上下文支持,以便为合适的对象中的每个过滤器(即,为流句柄、流、文件、实例或卷)存储上下文数据(例如,指针或类似物)。为了达到这个目的,本发明经由将上下文返回到实体的一组APIs来提供上下文支持,这样,简化了总过滤器上下文与那个实体的关联。可以随时设置并/或重置上下文。本发明也经由为实例设置通知的一组回收,来提供实例的通知支持。
实体类型包括实例、卷(本地磁盘卷或远程网络共享)、流(关于支持每一文件的多个流的文件系统)、流句柄(总文件对象)和文件(例如,文件的全部流)。关于实例,如下所述,当过滤器附属于卷时,创建实例;并且,也如上所述,可能有(例如,在同一卷上的另一个过滤器以上和以下所附属的)给定的卷的给定过滤器的一个以上的实例。每个实例可以具有关联的上下文,以便(例如)指向那个实例的专用记录。可以在各个过滤器实例之中共享卷上下文。
为了使上下文与对象相关联,过滤器调用FltAllocateContext( ),该FltAllocateContext( )指定上下文的类型(流句柄、流、文件、实例或卷)、上下文的大小以及是否应该从调页或非调页的组合存储器中定位上下文。一旦上下文被定位并被初始化,过滤器就通过调用合适的例行程序(FltSetStreamHandleContext( )、FltSetStreamContext( )、FltSetFileContext( )、FltSetInstanceContext( )或FltSetVolumeContext( ))来使上下文与对象相关联。
如图6中所表现的,为了有效率地查找跟文件、流和流句柄有关联的过滤器实例,过滤器管理器212将树(例如,分裂树)加入与文件对象有关联的各种数据结构。尤其是,操作系统促进将任意的上下文加入流,并且,过滤器管理器212使用这个机制将流控制清单608和树610加入FSRTL_ADVANCED_FCB_HEADER 612,文件对象614本质上经由其上下文616指向FSRTL_ADVANCED_FCB_HEADER 612。树610中的每个节点代表具有这个流的有关上下文的过滤器实例。虽然未分开示出,但是,如该过滤器实例为可能需要的不同类型的访问所指定的,可能会有并行树——一个用于调页组合存储器,另一个用于非调页组合存储器。
关于给定的流句柄,树中的每个节点由密钥(一种密钥是文件对象,另一种密钥是实例)来存取。注意,关于流,文件对象密钥是NULL。如图7中所表现的,当例如经由对过滤器管理器212内(或与过滤器管理器212有关联)的上下文机制412的功能调用中的数据而被提供这些密钥时,可以迅速为过滤器驱动器实例702定位树610中的合适的节点,合适的上下文704(例如,采用上下文指针的形式)已返回到请求过滤器驱动器实例702。在某种程度上,遍历是快速的,因为给定的配置中通常没有那么多过滤器实例。
在一项实施中,过滤器可以接收实例通知:
typedef PVOID PFLT_CONTEXT;NTSTATUS(*PFLT_INSTANCE_SETUP_CALLBACK)(IN CONST PFLT_RELATED_OBJECTS FltObjects,IN FLT_INSTANCE_SETUP_FLAGS Flags,IN DEVICE_TYPE VolumeDeviceType); |
如果特定的实例需要上下文,则可以在此回收中对其进行设置。该上下文是PVOID,系统将把它当作完全不透明,所以,过滤器可以使用它来存储标记域、计数器、指针或其所需要的任何其他事物。如果过滤器曾经能够成功地对其实例回收进行初始化并且愿意监控这个卷上的活动,则它应该返回STATUS_SUCCESS。如果过滤器不想在这个卷上创建该实例,则应该返回STATUS_FLT_DO_NOT_ATTACH。提供实例的通知清除回收,以便在新的操作可能涉及卷时适当地使实例拆卸同步化;并且,实例的通知清除回收包括InstanceQueryTeardown、InstanceTeardownStart和InstanceTeardownComplete。
为某个实体提供上下文结构的过滤器将会让其对应的ContextCleanupCallback被调用。换言之,为了避免使存储器组合泄漏,过滤器不需要了解它已定位哪些上下文,因为系统将会注意何时应该进行清除。当应该释放上下文时,系统调用过滤器的ContextCleanupCallback。在此回收期间,过滤器负责对上下文的内容进行非初始化(uninitialize),并且,一旦返回,系统将释放过滤器的较早的FltAllocateContext( )调用所定位的内存。假设清除完成;所以,不需要有返回值。系统也保证:将按IRQL来调用上下文清除例行程序,该IRQL足够低,以便可以安全地进行组合释放。
当过滤器与卷分开时,清除实例上下文。在卸载卷之后,并且在清除卷的所有文件、流和流句柄之后,清除卷上下文。由于存储管理器、高速缓冲管理器和文件系统实施细节的缘故,在卸载卷之后的相对较长的时间内,可能不会清除卷上下文。
当文件系统释放与文件有关联的内存时,清除文件上下文;在多流文件系统中,这将发生在释放那个文件的最后一个流的最后一个流句柄之后。注意,由于操作系统的存储管理器和高速缓冲管理器可能仍然和文件中的一个或多个流有关,因此,在关闭到该流的最后一个用户句柄之后的相对较长的时间内,可能不会清除文件上下文。同样,当文件系统释放与流有关联的内存时,清除流上下文;这将发生在释放那个流的最后一个流句柄之后。又由于操作系统的存储管理器和高速缓冲管理器可能仍然和文件中的一个或多个流有关,因此,在关闭到该流的最后一个用户句柄之后的相对较长的时间内,可能不会清除流上下文。
当释放对流句柄的最后参考时,清除流句柄上下文。这可能是因为正在关闭用户句柄或正在释放最后的存储管理器或高速缓冲管理器参考。
如果对象当前没有上下文,则可以为该对象设置上下文;或者,可以改变上下文。过滤器可以使用以下的例行程序之一来适当地清除上下文,这些例行程序是:FltDeleteContext( )、FltDeleteVolumeContext( )、FltDeleteInstanceContext( )、FltDeleteFileContex( )、FltDeleteStreamContext( )和FltDeleteStreamHandleContext( )。
过滤器将会经常想要有关实体的一些基本信息,以决定是否对其感兴趣。对于卷而言,这可能是文件系统,而不管该卷是本地的还是远程的,也不管它是否在可移动介质上,等等。对于文件而言,这可以包括该文件的名称、时间戳、大小和扩展名等。该系统可以暴露一些功能(例如,FltGetFileInformation( )、FltGetVolumeInformation( )),从而可以方便地检索该信息。过滤器也可能会希望调用FltTagFile( ),以便在文件上设置再分析点。
本发明的构造所提供的另一组APIs针对促进过滤器实例与用户状态码之间的通信。尤其是,许多过滤器具有通常是产品的管理部件的用户状态服务相对物,并且,过滤器需要与该服务进行通信。本构造可以为这些产品提供APIs,用于用户状态启动的通信和核心启动的通信。
例如,对于跟用户状态部件进行通信的过滤器而言,那些用户状态应用程序具备程序库。该程序库暴露例行程序,所包括的例行程序装载和卸载过滤器、使过滤器跟卷连接和分离、向来自用户状态的过滤器打开信道并发送/接收来自这些过滤器的数据、并且向系统询问有关系统的当前状态的信息。例如,用户状态程序可能会询问当前装载哪些过滤器、给定的卷上存在什么实例或给定的过滤器存在什么实例等。注意,过滤器-用户通信不同于所提供的管理APIs(允许列举过滤器/实例、卸载/装载过滤器等),因为过滤器可使用过滤器-用户通信APIs来进行自己的专用通信。
总之,新的过滤器模型提供了一种写入可靠、有效率的文件系统过滤器的方法,从而允许动态的装载/卸载、动态地与卷连接/分离、灵活的排序以及对过滤器通常最需要的一组充足的APIs进行存取。下文提供了关于基于WindowsNT/2000/XP操作系统的一项范例实施的具体细节。
范例实施
以下描述了经由功能调用而执行的部分过滤器启动操作(包括登记过滤器管理器):
过滤器宣布引起关注的I/O的回收:
FLT_OPERATION_REGISTRATION Callbacks[]={{IRP_MJ_CREATE,O, //FlagsAvCreate, //pre-callbackAvCreateCompletion}, //post-callback{IRP_MJ_WRITE,O,AvWrite,AvWriteCompletion},...}; |
过滤器宣布登记结构:
const FLT_REGISTRATION FilterRegistration={....AvUnload, // Unload routineAvInstanceSetup, // Instance SetupAvInstanceQueryTeardown,AvInstanceTeardownStart,AvInstanceTeardownComplete,......Callbacks, // Operation callbacks}; |
过滤器获得前回收:
status=FltRegisterFilter(DriverObject,&FilterRegistration,&AvFilterHandle); |
FLT_PRE_OPERATION_CALLBACK_STATUSAvWrite(IN OUT PFLT_CALLBACK_DATA Data,IN CONST PFLT_RELATED_OBJECTS FltObjects,OUT PVOID*CompletionContext); |
在这项范例实施中,文件系统过滤器驱动器包括NT核心状态驱动器,并照此被请求输出被称作“DriverEntry( )”的功能,该功能是当装载驱动器时被调用的第一项功能。当被装载时,过滤器调用功能,以便将命名的FltRegisterFilter( )登记在其DriverEntry( )中。FltRegisterFilter( )把参数作为FLT_REGISTRATION结构,该结构包含(在其他事物之中)实例设置和拆卸回收、上下文回收功能指针的清单以及文件系统操作的回收指针的清单。注意,在过滤器希望只与相对少量的操作挂钩并且只有兴趣为很少(如果有的话)的对象设置上下文的许多情况中,该清单可能非常短。
在一项选择性实施中,可能会有标记域,在该标记域中,过滤器设置可从中导出高度的一个或多个过滤器属性标记。例如,标记可以由过滤器来设置,该过滤器(例如)为加密或压缩过滤器修改数据,以便通知系统:它在去向和来自基文件系统的过程中修改数据。在这项实施中,将用户的数据分成多个流的任何过滤器也应该设置这个标记。过滤器也可以设置标记,以指出过滤器检查数据,例如,需要了解明码文本、未被压缩的数据的病毒过滤器将会设置这个标记。对于修改标准信息(例如,时间戳和日期)的过滤器、检查标准信息(例如,根据文件的日期来对该文件执行不同的操作)的过滤器、将创建改道到不同名称的文件/流的过滤器(例如,符号连接/SIS类型的过滤器)以及依靠文件名的过滤器(例如,扫描.EXE和.DOC文件的病毒过滤器)而言,也具备标记。
如上所述,可以使用这些标记来帮助系统按正确的顺序使过滤器附属于卷。例如,不应该允许抗病毒过滤器附属于加密过滤器与基文件系统之间,因为在加密之前,该抗病毒过滤器需要了解按现状的数据。为防止这一点,模型不允许具有指出过滤器检查数据标记集的标记的过滤器附属于具有指出过滤器修改数据的标记集的过滤器之上。另外,可以使用这些标记的某些组合来防止过滤器附属,例如,如果两个过滤器所设置的标记指出每个过滤器检查并修改数据,则这两个过滤器无法按任何顺序安全地附属于同一个卷。
以下阐明了各种文件系统过滤器驱动器的一种逻辑排序:
活动监视器(文件间谍等)恢复被删除的文件抗病毒复制连续备份内容筛选器定额管理簇文件系统HSM(第3方分级存储器管理程序)压缩加密 |
物理定额管理打开文件备份(打开文件的快照)安全增强器拷贝保护系统过滤器基础结构(过滤器管理器) |
如上所述,为了表示描述对过滤器驱动器的操作的必要信息,回收数据是I/O表示单位,有些类似于IRP。该回收数据包含专供文件系统过滤器使用的规格化参数,并且用于“快速I/O”调用、IRP调用和FsFilter调用。可改变的参数部分可以由驱动器来进行修改(即,弄脏),并且,如上所述,从一个过滤器到另一个过滤器,过滤器管理器经由完成节点堆栈间歇操作来遵守该参数部分。
以下是范例回收数据结构:
typedef struct_FLT_CALLBACK_DATA{....FLT_CALLBACK_DATA_FLAGS Flags;//// Thread that initiated this operation.//PETHREAD Thread;PFLT_IO_PARAMETER_BLOCK Iopb;IO_STATUS_BLOCK IoStatus;.....//other data:reparse data buffer,queuelinks,//context area for filters....} FLT_CALLBACK_DATA,*PFLT_CALLBACK_DATA; |
以下是范例I/O参数块:
typedef struct_FLT_IO_PARAMETER_BLOCK{............Uchar MajorFunction;Uchar MinorFunction;...........PFILE_OBJECT TargetFileObject;PFLT_INSTANCE TargetInstance ;//// Normalized parameters for the operation//FLT_PARAMETERS parameters;}FLT_IO_PARAMETER_BLOCK,*PFLT_IO_PARAMETER_BLOCK; |
操作前回收具有相同的签名:
FLT_PREOP_CALLBACK_STATUS(*PFLT_PRE_OPERATION_CALLBACK)(IN OUT PFLT_CALLBACK_DATA Data,IN CONST PFLT_RELATED_OBJECTS FltObjects,OUT PVOID*CompletionContext); |
如上所述,操作前回收可以返回FLT_PREOP_CALLBACK_STATUS的以下各个状态(和其他状态)中的一种状态:
FLT_PREOP_SUCCESS_WITH_CALLBACK——完成该操作,并且,过滤器想让其操作后回收被调用FLT_PREOP_SUCCESS_NO_CALLBACK——完成该操作,但是,过滤器不想让其操作后回收被调用FLT_PREOP_PENDING——过滤器驱动器在将来某个时间将会(通过调用FltCompletePendedPreOperation( ))完成该操作FLT_PREOP_COMPLETE——过滤器已完成该操作。操作可以通过设置错误状态而被舍弃,并可以返回这个回收状态。FLT_PREOP_SYNCHRONIZE——过滤器想要在曾在其中执行操作前回收的相同的线程上下文中执行完成处理;在完成这个I/O之前,将不会返回到引起这个I/O的线程。FLT_PREOP_DISALLOW_FASTIO——过滤器想要不准许执行给定的FastIo操作;这指出快速I/O路径不被准许,但是,I/O管理器将使用常规的IRP路径来完成该I/O。 |
操作后回收具有相同的签名:
FLT_POStop_CALLBACK_STATUS(*PFLT_POST_OPERATION_CALLBACK) (IN OUT PFLT_CALLBACK_DATA Data,IN CONST PFLT_RELATED_OBJECTS FltObjects,IN PVOID CompletionContext,IN FLT_POST_OPERATION_FLAGS Flags); |
这些标记可以包括:
FLTEL_POST_OPERATION_DRAINING——如果被设置的话,则分开给定的实例,并为清除处理而调用这个操作后例行程序。 |
FLT_POSTOP_CALLBACK_STATUS:
FLT_POStop_FINISHED_PROCESSING——过滤器已完成处理该操作FLT_POStop_MORE_PROCESSING_REQUIRED——过滤器驱动器在将来的某个时间将会(通过调用FltCompletePendedPostOperation)完成该操作FLT_POStop_UNDO_CREATE——过滤器想要撤消给定的创建操作 |
每一操作前回收,过滤器将接收一个完成回收。例如,如果内存被定位在前回收中,则可以保证将给过滤器在该完成回收中释放它的机会,并且该完成回收将不会被调用一次以上,来驱使过滤器释放该内存一次以上。
可以为其提供前、后回收的各项操作包括从IRP_MJ_CREATE到IRP_MJ_PNP的现存的IRP_MJ_代码、被创建来表示没有IRP相等物的快速I/O操作的IRP_MJ代码,以及被创建来表示FS过滤器操作的IRP_MJ代码。如果将来的操作系统版本增加新的IRP_MJ_代码,则现存的过滤器将不会受到影响,并且将不会接收在编译过滤器时不存在的IRP_MJ_例行程序的任何回收。如果过滤器登记操作系统没有认出的IRP_MJ_代码,则FltRegisterFilter( )将返回特殊的成功状态,并且只调用存在于那个版本中的功能的回收。如果过滤器不想继续运行,并且,如果将不会提供一个或多个回收,则该过滤器可以调用FltUnregisterFilter( )。
注意,将为基于IRP的I/O并为快速I/O调用IRP_MJ_READ和IRP_MJ_WRITE的回收。IRP_MJ_CREATE的前呼出将不会被传递文件或流的上下文,因为在创建前的时间,还没有确定将要创建什么文件或流(如果有的话)。IRP_MJ_CLOSE的后呼出将不会被传递任何上下文,因为在调用关闭后例行程序之前,会释放与这些上下文有关联的系统内部结构。IRP_MJ_CLEANUP和IRP_MJ_CLOSE的前回收必须完成,并且返回FLT_PREOP_SUCCESS_WITH_CALLBACK或FLT_PREOP_SUCCESS_NO_CALLBACK。
操作后回收有可能会在DPC层次处被调用,所以,它们不应该等候资源或互斥,也不应该调用将会等待的任何功能。注意,诸如FltSetFileContext( )的例行程序获取资源,因此可以不从操作后回收中被调用。
如上所述,后回收返回FLT_POSTOP_STATUS_SUCCESS或FLT_POSTOP_MORE_PROCESSING_REQUIRED。可以通过在IoStatus中设置错误代码,来舍弃后回收;一般而言,规则是:过滤器的责任是撤消已发生的任何动作。
除了动态地登记过滤器实例以外,还可以动态地分开过滤器实例,由此,将不再为那个卷上的任何操作调用这种过滤器实例。卸载过滤器本质上意味着:存储器中不再有它的代码。在系统关闭时间,并且当安装过滤器的新版本而没有关闭系统时,将最常卸载过滤器。注意,即使在有突出的I/O时,也可以分开过滤器实例。在那种情况下,将为具有标记FLTFL_POST_OPERATION_DRAINING集的任何突出的I/O操作调用过滤器的一个或多个完成例行程序。当那些I/O操作实际上完成时,过滤器将不会接收完成回收。关于与那个实例有关联的文件、流和流文件对象的突出的上下文,当过滤器实例被分开时,系统将调用例行程序来释放过滤器的上下文。
从前面详细的描述中可见,提供了一种处理大部分I/O处理要求的管理过滤器驱动器构造,从而促使过滤器驱动器更简单、可靠。这些驱动器只为其感兴趣的I/O进行有选择的登记,以便提高效率。实现了动态的装载和卸载、连接和分离。其他的好处包括上下文管理(包括对具有多流性能的文件系统的上下文管理)。这样,该方法和系统提供了当代计算中所需要的重要的优点和好处。
本发明容许经历各种修改并具备各种选择性结构,而其某些说明性实施例在附图中被示出,并已在上文加以详细的描述。但是,不言而喻,并不意在将本发明局限于所揭示的特殊形式,而正相反,本发明要包括在本发明的精神和范围以内的所有修改、选择性结构和相等物。