IoRegisterFsRegistrationChange 注册一个文件系统变动回调函数,用来被通知文件系统的激活和注销,激活是指第一次加载文件系统,当一个文件系统已经加载后,当加载一个同种文件系统的卷时,该文件系统就和激活没关系。话说该函数调用后,激活的文件系统会重新激活一遍,在2k SP4之后的系统都会这样做。
现在考虑下,这种机制是怎么实现的,猜测是在注册的时候,注册完成后,系统将各种类型的文件系统,都调用该回调函数一遍,来一次所有文件系统激活的通知。而事实上,也应该如此,reactOs的实现机制显示是这样的,奉上源码:
首先,先解释一些事情,目前系统会将各种类型的文件系统放到各自的链表队列中,如本地磁盘文件系统,ntfs和fat32文件系统,就在IopDiskFileSystemQueueHead队列中,其他类型的文件系统,如网络文件系统,是在IopNetworkFileSystemQueueHead中,cdrom文件系统,是在IopCdRomFileSystemQueueHead中,磁带文件系统,是在IopTapeFileSystemQueueHead队列中。
先看IoRegisterFsRegistrationChange的实现
下面是用的一些结构和数据
该函数的实现还是比较简单的,先查询保存FS_CHANGE_NOTIFY_ENTRY结构的这张链表IopFsNotifyChangeQueueHead,如果要注册的driveobject和回调函数地址都一样,就不再重复注册,如果未注册,分配内存,将该结构填充后插到链表尾部,然后,也就是我们猜想的部分的实现,确实是各种类型的文件系统队列,依次调用该回调函数就行文件系统激活的通知。
看下IopNotifyAlreadyRegisteredFileSystems函数的实现:
依次遍历各种类型的文件系统队列,然后依次调用该回调函数进行通知,在判断的时候,对最后一个节点,和rawfs结合起来判断了,关于rawfs的东西,目前还不是很清楚,这里不做解释。
现在,就明白这个问题了,当文件系统已经加载了,注册文件激活通知,是如何得到通知的。
在文件过滤驱动中,该函数主要应用场景是,当一个新增的卷要挂载时,我们如何实时地挂载到这个卷上,就可以调用该函数,得到各个文件系统的控制设备,然后attach上去,那么块设备在挂载卷设备时,会向文件系统控制设备发送irp_mj_file_system_control的irp,我们挂载文件系统控制设备后,就会先得到通知,然后取出里面的vpb对应的realdeivce对象保存起来,当该irp在真正的文件系统控制设备完成后,我们根据保存的vpb获取对应的deviceobject,即新挂载的卷设备,这样就可以实时attach到这个新增的卷设备上了,从而能对新增的卷设备进行及时的管控或设计。