要求和授與 oplock
當網路重新導向器存取遠端伺服器上的檔案時,它會從遠端伺服器要求 oplock。 只有在鎖定適用於本機伺服器上的檔案時,用戶端應用程式才會直接要求oplock。
Oplock 是透過 FSCTL 要求。 下列 FSCTL 用於不同的 oplock 類型,使用者模式應用程式和核心模式驅動程式都可以發出:
- 若要要求舊版 oplock:
- 若要要求 Windows 7 oplocks:
若要在使用者模式中要求 Windows 7 oplock,請呼叫 DeviceIoControl:
- 將 dwIoControlCode 設定為 FSCTL_REQUEST_OPLOCK。
- 在REQUEST_OPLOCK_INPUT_BUFFER結構的 Flags 成員中指定 REQUEST_OPLOCK_INPUT_FLAG_REQUEST 旗標,此成員會傳遞為 lpInBuffer 參數。
以類似的方式要求核心模式中的 Windows 7 oplock:
- 非文件系統迷你篩選程式可以呼叫 ZwFsControlFile。
- 文件系統迷你篩選器必須使用 FltAllocateCallbackData 和 FltPerformAsynchronousIo。
若要指定需要四個 Windows 7 oplock 中的哪一個,請在 REQUEST_OPLOCK_INPUT_BUFFER 結構的 RequestedOplockLevel 成員中設定下列一或多個旗標:
- OPLOCK_LEVEL_CACHE_READ
- OPLOCK_LEVEL_CACHE_HANDLE
- OPLOCK_LEVEL_CACHE_WRITE
如需詳細資訊,請參閱 FSCTL_REQUEST_OPLOCK。
如果可以授與要求的 oplock,文件系統會傳回STATUS_PENDING。 基於這個理由,永遠不會授與同步 I/O 的 oplock。 FSCTL IRP 在作業鎖定中斷之前不會完成。
如果無法授與 oplock,則會傳回文件系統傳回適當的錯誤碼。 最常見的傳回錯誤碼是STATUS_OPLOCK_NOT_GRANTED和STATUS_INVALID_PARAMETER (,以及其對等的使用者模式類比) 。
當其他應用程式/用戶端嘗試存取相同的數據流時,Filter oplock 可讓應用程式「回復」。 此機制可讓應用程式存取數據流,而不會造成數據流的其他存取子在嘗試開啟數據流時收到共享違規。 若要避免共用違規,應該使用特殊的三步驟程式來要求篩選 oplock (FSCTL_REQUEST_FILTER_OPLOCK) :
開啟具有必要存取權的檔案,FILE_READ_ATTRIBUTES和FILE_SHARE_READ的共用模式 |FILE_SHARE_WRITE |FILE_SHARE_DELETE。
從步驟 1 要求句柄上的篩選作業鎖定。
再次開啟檔案以供讀取存取。
在步驟 1 中開啟的句柄不會造成其他應用程式收到共用違規,因為它只會針對屬性存取 (FILE_READ_ATTRIBUTES) 開啟,而不是數據存取 (FILE_READ_DATA) 。 此句柄適用於要求篩選作業鎖定,但不適用於在數據流上執行實際 I/O。 在步驟 3 中開啟的句柄可讓 oplock 的持有者在數據流上執行 I/O;在步驟 2 中授與的 oplock 可讓 oplock 的持有者「離開」,而不會造成嘗試存取數據流的另一個應用程式發生共享違規。
NTFS 檔案系統透過建立選項旗標FILE_RESERVE_OPFILTER提供此程序的優化。 如果在上一個程式的步驟 1 中指定這個旗標,它可讓文件系統在文件系統判斷步驟 2 將會失敗時,讓建立要求失敗,並STATUS_OPLOCK_NOT_GRANTED。 如果步驟 1 成功,則即使為建立要求指定了FILE_RESERVE_OPFILTER,步驟 2 也不會保證會成功。
下表識別授與 oplock 所需的必要條件。
要求類型 | 條件 |
---|---|
層級 1 篩選 Batch |
只有在下列所有條件都成立時,才會授與:
如果目前的 oplock 狀態為:
|
層級 2 |
只有在下列所有條件都成立時,才會授與:
如果目前的 oplock 狀態為:
|
讀取 |
只有在下列所有條件都成立時,才會授與:
請注意,如果目前的 oplock 狀態為:
|
Read-Handle |
只有在下列所有條件都成立時,才會授與:
如果目前的 oplock 狀態為:
|
Read-Write |
只有在下列所有條件都成立時,才會授與:
如果目前的 oplock 狀態為:
|
可擦寫的句柄 |
只有在下列所有專案都成立時,才會授與:
如果目前的 oplock 狀態為:
|
注意
讀取和層級 2 oplock 可以共存於相同的數據流上,而讀取和 Read-Handle oplock 可以共存,但層級 2 和 Read-Handle oplock 無法共存。