首頁  >  文章  >  後端開發  >  如何使用 FSCTL_ENUM_USN_DATA 有效檢測 NTFS 磁碟區上的檔案變更?

如何使用 FSCTL_ENUM_USN_DATA 有效檢測 NTFS 磁碟區上的檔案變更?

Patricia Arquette
Patricia Arquette原創
2024-10-30 13:03:26809瀏覽

 How Can You Efficiently Detect File Changes on an NTFS Volume Using FSCTL_ENUM_USN_DATA?

使用FSCTL_ENUM_USN_DATA 高效檢測NTFS 磁碟區上的檔案變更

背景

檢查每個檔案的存檔位的現有方法可能會變備份方法可能會變備份得緩慢且緩慢對於大型檔案系統效率低。此方法需要掃描所有文件,包括臨時文件,並可能導致冗長的備份過程。

使用檔案系統 USN 的替代方法

更有效的方法涉及使用檔案系統 USN(更新序列)號碼)來變更日誌。檔案系統 USN 提供對檔案系統所做的每個變更的記錄,包括檔案建立、刪除和修改。

FSCTL_ENUM_USN_DATA 的工作原理

要檢測 NTFS 磁碟區上的更改,我們可以利用FSCTL_ENUM_USN_DATA 控制碼。此控制碼:

  • 枚舉磁碟區上的所有文件,僅包括目前存在的文件。
  • 檢索每個文件的關鍵數據,包括:

    • 文件標誌
    • USN
    • 文件名
    • 父檔參考號

實作變更偵測

偵測變更:

  1. 取得檔案系統USN 資料: 使用FSCTL_QUERY_USN_JOURNAL 取得系統的最大USN (maxusn)。
  2. 列舉 USN 記錄: 使用 FSCTL_ENUM_USN_DATA 循環遍歷 USN 記錄。
  3. 辨識相關記錄: 檢查標誌並比較 USN 以偵測已建立、刪除或修改的檔案。
  4. 解析父路徑:將父檔案參考號碼與目錄的檔案參考號碼相符,以獲得完整的檔案路徑。

C 程式碼範例

這是示範此方法的程式碼片段:

<code class="c++">DWORDLONG nextid;
DWORDLONG filecount = 0;
DWORD starttick, endtick;

// Allocate memory for USN records
void * buffer = VirtualAlloc(NULL, BUFFER_SIZE, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);

// Open volume handle
HANDLE drive = CreateFile(L"\\?\c:", GENERIC_READ, FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_ALWAYS, FILE_FLAG_NO_BUFFERING, NULL);

// Get volume USN journal data
USN_JOURNAL_DATA * journal = (USN_JOURNAL_DATA *)buffer;
if (!DeviceIoControl(drive, FSCTL_QUERY_USN_JOURNAL, NULL, 0, buffer, BUFFER_SIZE, &bytecount, NULL)) {
  (...)
}
maxusn = journal->MaxUsn;

MFT_ENUM_DATA mft_enum_data;
mft_enum_data.StartFileReferenceNumber = 0;
mft_enum_data.LowUsn = 0;
mft_enum_data.HighUsn = maxusn;

while (...) {
  if (!DeviceIoControl(drive, FSCTL_ENUM_USN_DATA, &mft_enum_data, sizeof(mft_enum_data), buffer, BUFFER_SIZE, &bytecount, NULL)) {
    (...)
  }

  nextid = *((DWORDLONG *)buffer);
  USN_RECORD * record = (USN_RECORD *)((USN *)buffer + 1);
  USN_RECORD * recordend = (USN_RECORD *)(((BYTE *)buffer) + bytecount);

  while (record < recordend) {
    filecount++;
    // Check flags and USNs to identify changes
    (...)
    record = (USN_RECORD *)(((BYTE *)record) + record->RecordLength);
  }
  mft_enum_data.StartFileReferenceNumber = nextid;
}</code>

效能注意事項

使用FSCTL_ENUM_USN_DATA 的方法提供:

  • 快速列舉過程: 每秒能夠處理超過6000 筆記錄。
  • 高效過濾: 僅分析相關的文件更改記錄,消除臨時文件的開銷。
  • 潛力限制: 在非常大的捲上效能可能會有所不同,但它通常比檢查存檔位更有效。

附加說明

  • 在 Windows 上將 MFT_ENUM_DATA 替換為 MFT_ENUM_DATA_V0 Windows 7 之後的版本。
  • 文件參考號碼列印為 32 位,這是一個錯誤。在生產代碼中,建議使用 64 位元值。

以上是如何使用 FSCTL_ENUM_USN_DATA 有效檢測 NTFS 磁碟區上的檔案變更?的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn