我的目的是通過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。