Recognizer & FS & Filter

本文详细解析了Windows操作系统中文件系统的加载过程,包括文件系统识别器、文件系统过滤器的工作原理,以及它们如何通过特定的API进行交互。重点介绍了文件系统注册、文件系统变化通知等关键环节。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

注一: File system recognizer 文件系统识别器(下文简称为recognizer) File system            文件系统     (下文简称为fs) File system filter     文件系统过滤器(下文简称为filter)

文件系统识别器是一个标准的NT内核模式驱动程序;它只实现一项功能:检查物理介质设备,如果它能够识别存储介质的格式便加载相应的文件系统驱动程序,利用它主要是为节约系统内存,文件系统驱动程序没用到时为什么让他在内存中呢?

               文件系统过滤驱动的一般处理流程(参照sfilter):

                     DriverEntry                         ||                         ||初始化dispatch表中的IRP_MJ_FILE_SYSTEM_CONTROL                         ||routine                         ||              DriverObject->MajorFunction[IRP_MJ_FILE_SYSTEM_CONTROL] = SfFsControl ...                         ||                         ||注册一个SfFsNotification;当文件系统或文件系统识别器                         ||registers or unregisters时被调用                         ||     IoRegisterFsRegistrationChange(DriverObject, SfFsNotification)                         ||                         ||                         //      SfFsNotification(PDEVICE_OBJECT DeviceObject, BOOLEAN FsActive)                         ||                         || FsActive         TRUE <----------//------------> FALSE          ||                              ||          ||                              || IoAttachDeviceToDeviceStack         IoDetachDevice          ||          ||  /-------//------->Attach to (Filesystem)-----------------/IRP_MJ_FILE_SYSTEM_CONTROL  |                                                        |  |                                                        |MN:IRP_MN_MOUNT_VOLUME  /---------------->Attach to (recognizer)                 |你就尽管Mount,只要fs                         ||                                |处理状态为STATUS_SUCCESS;                         ||MJ:IRP_MJ_FILE_SYSTEM_CONTROL   |fs中关于卷的Mount处理                         //                                |参见FatMountVolume函数     SfFsControl (PDEVICE_OBJECT DeviceObject, PIRP Irp)   |                         ||                                //filter其他处理参见sfilter                         ||MN:              /--------------//-----------------------------/          |                                             |          |IRP_MN_MOUNT_VOLUME                          |          |                                             |  filter等待recognizer处理完成                                    ||                                            |          ||                                            |    /-----//-->STATUS_FS_DRIVER_REQUIRED(1)---|/        |    |                                         ||           /-------->STATUS_UNRECOGNIZED_VOLUME(2)---||                                                     ||        |                                              ||        |                                              //        | 不论结果是哪一个,filter什么动作也没有;                  但IO管理器收到recognizer处理结果后,处理各不相同:           (1)表示recognizer认识这个卷,但对应的fs还没启动             | (2)表示recognizer不认识这个卷,对应的fs不能处理            ||  如果是第一种情况I/O管理器就会向这个设备发送---------------||IRP_MN_LOAD_FILE_SYSTEM                                                       ||                                                       ||原来我们一直挂接在recognizer上的                                                       //                                                  IoDetachDevice(recognizer)                                                       ||                                                       ||                                              wait recognizer load fs status                                                       ||                                                       ||                               Other status<-----------//----------->STATUS_SUCCESS                                  ||                                                                       ||recognizer加载对应的fs失败                                  ||只好还挂到recognizer上                                  ||                                  //                   IoAttachDeviceToDeviceStack(recognizer)

 

注二:IoRegisterFsRegistrationChange函数 在winxp,win2003下会对已加载的文件系统重新枚举一遍 而nt4.0和win2000下则不会,具体原因代码见... (留意一下IopNotifyAlreadyRegisteredFileSystems的作用和实现) //win2000 NTSTATUS IoRegisterFsRegistrationChange(     IN PDRIVER_OBJECT DriverObject,     IN PDRIVER_FS_NOTIFICATION DriverNotificationRoutine     )

/*++

Routine Description:

    This routine registers the specified driver's notification routine to be     invoked whenever a file system registers or unregisters itself as an active     file system in the system.

Arguments:

    DriverObject - Pointer to the driver object for the driver.

    DriverNotificationRoutine - Address of routine to invoke when a file system         registers or unregisters itself.

Return Value:

    The return status is the final value of the function.

--*/

{     PNOTIFICATION_PACKET nPacket;

    PAGED_CODE();

    //     // Begin by attempting to allocate storage for the shutdown packet.  If     // one cannot be allocated, simply return an appropriate error.     //

    nPacket = ExAllocatePoolWithTag( PagedPool,                                      sizeof( NOTIFICATION_PACKET ),                                      'sFoI' );     if (!nPacket) {         return STATUS_INSUFFICIENT_RESOURCES;     }

    //     // Initialize the notification packet and insert it onto the tail of the     // list.     //

    nPacket->DriverObject = DriverObject;     nPacket->NotificationRoutine = DriverNotificationRoutine;

    ExAcquireResourceExclusive( &IopDatabaseResource, TRUE );     InsertTailList( &IopFsNotifyChangeQueueHead, &nPacket->ListEntry );     ExReleaseResource( &IopDatabaseResource );

    //     // Increment the number of reasons that this driver cannot be unloaded.     //

    ObReferenceObject( DriverObject );

    return STATUS_SUCCESS; }

 

//win2003 NTSTATUS IoRegisterFsRegistrationChange(     IN PDRIVER_OBJECT DriverObject,     IN PDRIVER_FS_NOTIFICATION DriverNotificationRoutine     )

/*++

Routine Description:

    This routine registers the specified driver's notification routine to be     invoked whenever a file system registers or unregisters itself as an active     file system in the system.

Arguments:

    DriverObject - Pointer to the driver object for the driver.

    DriverNotificationRoutine - Address of routine to invoke when a file system         registers or unregisters itself.

Return Value:

    STATUS_DEVICE_ALREADY_ATTACHED -                 Indicates that the caller has already registered                 last with the same driver object & driver notification

    STATUS_INSUFFICIENT_RESOURCES     STATUS_SUCCESS

--*/

{     PNOTIFICATION_PACKET nPacket;

    PAGED_CODE();

    ExAcquireResourceExclusiveLite( &IopDatabaseResource, TRUE );

    if (!IsListEmpty( &IopFsNotifyChangeQueueHead )) {

        //         // Retrieve entry at tail of list         //

        nPacket = CONTAINING_RECORD( IopFsNotifyChangeQueueHead.Blink, NOTIFICATION_PACKET, ListEntry );

        if ((nPacket->DriverObject == DriverObject) &&             (nPacket->NotificationRoutine == DriverNotificationRoutine)) {

            ExReleaseResourceLite( &IopDatabaseResource);             return STATUS_DEVICE_ALREADY_ATTACHED;         }     }

    //     // Begin by attempting to allocate storage for the shutdown packet.  If     // one cannot be allocated, simply return an appropriate error.     //

    nPacket = ExAllocatePoolWithTag( PagedPool|POOL_COLD_ALLOCATION,                                      sizeof( NOTIFICATION_PACKET ),                                      'sFoI' );     if (!nPacket) {

        ExReleaseResourceLite( &IopDatabaseResource );         return STATUS_INSUFFICIENT_RESOURCES;     }

    //     // Initialize the notification packet and insert it onto the tail of the     // list.     //

    nPacket->DriverObject = DriverObject;     nPacket->NotificationRoutine = DriverNotificationRoutine;

    InsertTailList( &IopFsNotifyChangeQueueHead, &nPacket->ListEntry );

    IopNotifyAlreadyRegisteredFileSystems(&IopNetworkFileSystemQueueHead, DriverNotificationRoutine, FALSE);     IopNotifyAlreadyRegisteredFileSystems(&IopCdRomFileSystemQueueHead, DriverNotificationRoutine, TRUE);     IopNotifyAlreadyRegisteredFileSystems(&IopDiskFileSystemQueueHead, DriverNotificationRoutine, TRUE);     IopNotifyAlreadyRegisteredFileSystems(&IopTapeFileSystemQueueHead, DriverNotificationRoutine, TRUE);

    //     // Notify this driver about all already notified filesystems     // registered as an active file system of some type.     //

    ExReleaseResourceLite( &IopDatabaseResource );

    //     // Increment the number of reasons that this driver cannot be unloaded.     //

    ObReferenceObject( DriverObject );

    return STATUS_SUCCESS; }

VOID IopNotifyAlreadyRegisteredFileSystems(     IN PLIST_ENTRY  ListHead,     IN PDRIVER_FS_NOTIFICATION DriverNotificationRoutine,     IN BOOLEAN SkipRaw     ) /*++

Routine Description:

    This routine calls the driver notification routine for filesystems     that have already been registered at the time of the call.

Arguments:

    ListHead - Pointer to the filesystem registration list head.     DriverNotificationRoutine - Pointer to the routine that has to be called.

Return Value:

    None.

--*/ {     PLIST_ENTRY entry;     PDEVICE_OBJECT fsDeviceObject;

    entry = ListHead->Flink;     while (entry != ListHead) {

        //         // Skip raw filesystem notification         //         if ((entry->Flink == ListHead) && (SkipRaw)) {             break;         }

        fsDeviceObject = CONTAINING_RECORD( entry, DEVICE_OBJECT, Queue.ListEntry );         entry = entry->Flink;         DriverNotificationRoutine( fsDeviceObject, TRUE );     } }

注三:IoRegisterFileSystem函数 是文件系统在DriverEntry中最后要调用的函数,主要是向IO管理器中注册一下,以后有卷需要Mount时通知我... VOID IoRegisterFileSystem(     IN OUT PDEVICE_OBJECT DeviceObject     )

/*++

Routine Description:

    This routine inserts the device object for the file system which the device     object represents into the list of file systems in the system.

Arguments:

    DeviceObject - Pointer to device object for the file system.

Return Value:

    None.

--*/

{     PNOTIFICATION_PACKET nPacket;     PLIST_ENTRY entry;

    PAGED_CODE();

    //     // Allocate the I/O database resource for a write operation.     //

    (VOID) ExAcquireResourceExclusive( &IopDatabaseResource, TRUE );

    //     // Insert the device object into the appropriate file system queue based on     // the driver type in the device object.  Notice that if the device type is     // unrecognized, the file system is simply not registered.     //

    if (DeviceObject->DeviceType == FILE_DEVICE_NETWORK_FILE_SYSTEM) {         InsertHeadList( &IopNetworkFileSystemQueueHead,                         &DeviceObject->Queue.ListEntry );     } else if (DeviceObject->DeviceType == FILE_DEVICE_CD_ROM_FILE_SYSTEM) {         InsertHeadList( &IopCdRomFileSystemQueueHead,                         &DeviceObject->Queue.ListEntry );     } else if (DeviceObject->DeviceType == FILE_DEVICE_DISK_FILE_SYSTEM) {         InsertHeadList( &IopDiskFileSystemQueueHead,                         &DeviceObject->Queue.ListEntry );     } else if (DeviceObject->DeviceType == FILE_DEVICE_TAPE_FILE_SYSTEM) {         InsertHeadList( &IopTapeFileSystemQueueHead,                         &DeviceObject->Queue.ListEntry );     }

    //     // Ensure that this file system's device is operable.     //

    DeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;

    //     // Notify all of the registered drivers that this file system has been     // registered as an active file system of some type.     //

    //PS:看到了吧,如果你的filter调用了IoRegisterFsRegistrationChange,     //文件系统注册时就要通过你啦,TRUE-Load/FALSE-unload.     entry = IopFsNotifyChangeQueueHead.Flink;     while (entry != &IopFsNotifyChangeQueueHead) {         nPacket = CONTAINING_RECORD( entry, NOTIFICATION_PACKET, ListEntry );         entry = entry->Flink;         nPacket->NotificationRoutine( DeviceObject, TRUE );     }

    //     // Release the I/O database resource.     //

    ExReleaseResource( &IopDatabaseResource );

    //     // Increment the number of reasons that this driver cannot be unloaded.     //

    ExInterlockedAddUlong( &DeviceObject->ReferenceCount, 1, &IopDatabaseLock ); }

注四:    有兴趣的话可以看看文件识别器,IO管理器,文件系统的实现.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值