Everything实现原理

一、USN Journal及MFT原理

everything搜索文件的速度之所以快得令人愤怒,主要原因是利用了NTFS的USNJournal特性,直接从系统的主文件表里读取文件信息。

       USNJournal(Update SequenceNumber Journal)也被称作Change Journal。微软在NTFS 5.0(Windows 2000)中引入了USN Journal特性。USN Journal实际上是NTFS分区的一个日志文件,包含了所有对分区操作(文件操作)的记录。操作系统为每一个扇区单独维护一个USN Journal。当扇区的文件有变化时,操作系统会往USN Journal文件中追加一条记录,该记录包含文件名、变化发生的时间、变化的原因等信息,而不包含变化的内容。每一条记录用一个64位数字标识,称作USN(UpdateSequence Number)。微软用每一条记录在日志文件中的偏移作为该记录的USN,这样可以快速地通过USN获取到对应的记录。显而易见,USN是递增的,但是不连续。同时,由于文件名有长有短,每条记录的长度也不固定。在日志文件中,以文件块的形式存储记录。每个文件块大小为4K(USN_PAGE_SIZE),按每条记录100字节计,可以存储30~40条记录。单条记录不允许跨块存储。

       USNJournal也有一个64位的ID(Journal ID)。当文件/目录发生变化时,系统除了往USN Journal追加一条日志外,也会更新Journal ID。如果Journal ID没有更新,意味着文件系统没有任何变化。

       对NTFS分区,文件信息存储于主文件表(Master File Table,MFT)。MFT是NTFS的核心。主文件表里的每条记录包含文件和目录的所有信息,例如文件名/目录名、路径、大小、属性等。此外,还会存储该文件/目录最后一次变化对应的USN,系统在更新USN Journal时,也会更新这个字段。

       小提示:可以用FSUtil.exe获取NTFS信息。FSUtil.exe FSInfoNTFSInfo C:

二、相关API

Windows提供了一系列API供应用程序访问USN Journal及MFT。相关的函数及数据结构罗列如下:

l  DeviceIoControl 

l  FSCTL_QUERY_USN_JOURNAL

l  struct USN_JOURNAL_DATA

l  FSCTL_ENUM_USN_DATA

l  FSCTL_READ_USN_JOURNAL

l  struct USN_RECORD

 

DeviceIoControl如何使用请查阅MSDN。FSCTL_QUERY_USN_JOURNAL和FSCTL_READ_USN_JOURNAL是DeviceIoControl的两个控制码,分别用于读取USN Journal统计信息和USN Journal记录。

USN_JOURNAL_DATA是USN Journal统计信息结构体,定义如下:

typedefstruct {

    DWORDLONG UsnJournalID;

    USN FirstUsn;

    USN NextUsn;

    USN LowestValidUsn;

    USN MaxUsn;

    DWORDLONG MaximumSize;

    DWORDLONG AllocationDelta;

}USN_JOURNAL_DATA, *PUSN_JOURNAL_DATA;

 

Members 

Description 

UsnJournalID 

64-bit unique journal identifier. 

FirstUsn 

Identifies the first USN actually in the journal. All USNs below this value have been purged. 

NextUsn 

The USN that will be assigned to the next record appended to the journal. 

LowestValidUsn

The lowest USN that is valid for this journal. On some occasions, the lowest USN number may not be zero. All changes with this USN or higher have been reported in the Change Journal. 

MaxUsn 

The largest USN that will ever be issued in this journal. USNs cannot make use of the entire 64-bit address space-they are limited by the maximum logical size of a sparse file on an NTFS volume. Administrators are responsible for watching this number and deleting the journal if the NextUsn member approaches this value. 

MaximumSize 

The maximum size in bytes that the journal should use on the volume. 

AllocationDelta 

Size to grow the journal when needed, and size to purge from the start of the journal if it grows past MaximumSize. 

 

USN Journal文件中,每一项记录的结构如下:

// Version 2.0 USN_RECORD structure

 typedef struct {

     DWORD         RecordLength;

     WORD          MajorVersion;

     WORD          MinorVersion;

     DWORDLONG     FileReferenceNumber;

     DWORDLONG     ParentFileReferenceNumber;

     USN Usn;

     LARGE_INTEGER TimeStamp;

     DWORD         Reason;

     DWORD         SourceInfo;

     DWORD         SecurityId;

     DWORD         FileAttributes;

     WORD          FileNameLength;

     WORD          FileNameOffset;

     WCHAR         FileName[1];

 } USN_RECORD, *PUSN_RECORD;

Members 

Description 

RecordLength

Total length of the record.

MajorVersion

USN Journal’s version.

MinorVersion

FileReferenceNumber

A File Reference Number (FRN) is 64-bit ID that uniquely identifies any file or directory on an NTFS volume.

ParentFileReferenceNumber

Parent’s FRN. It’s always a directory FRN.

Usn

Record’s update sequence number.

TimeStamp

Standard UTC time stamp of this record, in 64-bit format. 

Reason

Tells you what sorts of changes have occurred to the file or directory. The Reason member may have one or more of the reason codes set.

SourceInfo

Ignore

SecurityId

FileAttributes

File information.

FileNameLength

FileNameOffset

FileName

三、实现思路

出于项目保密考虑,这里只大致介绍一下实现思路。

首先对每一个分区用FSCTL_ENUM_USN_DATA遍历文件和目录,建立索引;然后用FSCTL_READ_USN_JOURNAL监控系统中的文件变化(可只监听感兴趣的变化,如新建、删除、改名等操作),更新索引;退出程序时将索引保存到文件中,供下次启动时加载。

四、扩展思考

1.   如何由FRN获取文件/目录的路径?

Windows没有提供相应的API来完成这个功能。只有先建立索引树,然后遍历索引树得到完整的路径。

2.  关闭everything之后的文件变化,重启everything之后如何扫描到?

用FSCTL_ENUM_USN_DATA遍历至MFT的最后一项时,会返回USN Journal最后一项的USN。保存下来,下次重启Everything时,从该USN重新开始遍历即可。

3.  怎样从MFT里获取文件的访问时间?

利用控制码FSCTL_GET_NTFS_FILE_RECORD可以获取MFT里的一条记录。使用时需要提供文件的FRN(FileReferenceNumber)。实现细节可参考以下文章

http://www.codeproject.com/Articles/9293/Undelete-a-file-in-NTFS

http://blog.csdn.net/problc/article/details/5971825


  • 6
    点赞
  • 35
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值