利用windows UsnJournal实现文件搜索时遇到的问题

我的目的是通过windows UsnJournal的特性实现NTFS格式本地磁盘的文件快速搜索。在获取全盘文件信息时,如果每次都遍历MFT,则会消耗几秒的时间和较大的系统资源。所以应该在第一次遍历MFT后,根据UsnJournal中的记录来更新全盘文件信息。但是当我遍历完MFT并将其数据存储后,在处理UsnJournal记录时发现对于某些删除行为(reason为USN_REASON_DELETE)对应的文件并没有出现在之前建立的数据库中,显然删除一个不存在的文件是错误的,网上搜了一下发现没人提出过这样的问题。首先我以为是之前遍历MFT时获取的数据不全面,导致数据库中缺少文件,但是反复检查也没有发现代码错误,后来我以为是读取UsnJournal记录时读取到了错误的记录,但是好像也没发现错误,现在猜的是当遍历MFT表时,MFT表可能也在变化之中。在这里插入图片描述
假设上图就是MFT表,假设我们遍历到2号文件时,3号文件被删除,则此时会生成3号文件的UsnJournal记录,记录了其删除操作,但是MFT中已没有了3号文件,所以遍历从2号跳到了4号,最终数据库中没有3号文件,但是读取UsnJournal记录时会读到3号的删除记录,从而产生了之前提到的错误,听起来是有点道理的,但不知道对不对。经过测试,解决方法就是第一次根据UsnJournal记录更新数据库时,忽略这种错误,当之后再次更新时,数据库已是准确的,不会出现上述情况。

另一种错误是当读取UsnJournal记录时遇到某些创建操作,但是对应的文件在数据库中已经存在,显然创建一个已经存在的文件也是错的,假设程序没问题的话,那么可能也是由于类似上述问题的原因,以上图为例,遍历时,3号文件存在于MFT表中,所以3号文件被读到且存于数据库中,但是由于3号文件带有USN_REASON_CLOSE的创建记录不一定立刻生成,可能在之后的某个时刻才生成,所以当之后读到这条UsnJournal记录时,发生重复创建错误,忽略即可,至于是不是真的因为这,之后再建例子验证。
引用网上一篇文章中说的“系统追踪每一个打开文件的原因变量。当系统第一回打开文件,会设置原因变量为0。文件打开时,没有记录添加。如果变化真的发生了,系统检查原因码是否在原因变量里标记了。如果这是一个新的原因码,原因变量里就有新的位设置,一条记录添加到更改日志(原因变量拷贝到记录的reason中)。可能不止一个程序在修改文件和目录,原因变量会为文件所有变化来积累原因码、原因变量继续积累变化原因位的链表一直到文件句柄关闭才结束。就在这时,最终的记录添加到更改日志中,带有积攒的原因码USN_REASON_CLOSE。
所以如果有两个进程A和B,A创建打开一个新文件f,B打开文件f,A退出时,一条不带close的记录被添加到日志中,因为f的句柄还没关闭,当之后B退出时,f句柄关闭,一条带有close的记录被添加到日志中,在B退出之前我们遍历mft时会录入f,当B退出后我们查找日志时才发现这条创建记录,所以产生了创建一个已经存在的文件错误。根据这种思路测试了一番,顺序为:进程A创建打开文件f,进程B打开文件f,进程A退出,枚举主文件表,进程B退出,根据UsnJournal记录更新数据库。果然发生了重复创建的现象,解决方法就是忽略qwq。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值