使用移除鎖定
拿掉鎖定例程提供一種方式來追蹤裝置上未處理的 I/O 作業數目,以及判斷何時可以安全地卸離和刪除驅動程式的裝置物件。 系統會將這些例程提供給驅動程式寫入器,作為實作自己追蹤機制的替代方案。
驅動程式可以使用此機制進行兩個用途:
為了確保驅動程式的 DispatchPnP 例程不會在鎖定保留時完成IRP_MN_REMOVE_DEVICE要求(例如,另一個驅動程式例程正在存取裝置)。
若要計算驅動程式不應該刪除其裝置物件的原因數目,並在該計數達到零時設定事件。
若要初始化移除鎖定,驅動程式應該在其裝置擴充功能中配置IO_REMOVE_LOCK結構,然後呼叫 IoInitializeRemoveLock。 當驅動程式初始化裝置對象的其餘裝置擴充功能時,驅動程式通常會在其 AddDevice 例程中呼叫 IoInitializeRemoveLock。
您的驅動程式每次啟動 I/O 作業時,都必須呼叫 IoAcquireRemoveLock。 每次完成 I/O 作業時,驅動程式都必須呼叫 IoReleaseRemoveLock。 驅動程式可以多次取得鎖定。 拿掉鎖定例程會維護鎖定未完成的擷取計數。 對 IoAcquireRemoveLock 的每個呼叫都會遞增計數,而 IoReleaseRemoveLock 會遞減計數。
當您的驅動程式傳遞其程式代碼的參考時,也應該呼叫 IoAcquireRemoveLock (適用於定時器、DPC、回呼等等)。 然後,驅動程式必須在傳回事件時呼叫 IoReleaseRemoveLock 。
在IRP_MN_REMOVE_DEVICE的分派程序代碼中,驅動程式必須再次取得鎖定,然後呼叫 IoReleaseRemoveLockAndWait。 在釋放鎖定的所有未完成取得之前,此例程才會傳回。 若要允許排入佇列的 I/O 作業完成,每個驅動程式都應該在將IRP_MN_REMOVE_DEVICE要求傳遞至下一個較低的驅動程式之後呼叫 IoReleaseRemoveLockAndWait,並在它釋放記憶體之前,呼叫 IoDetachDevice 或呼叫 IoDeleteDevice。 在針對特定移除鎖定呼叫IoReleaseRemoveLockAndWait之後,所有針對相同移除鎖定呼叫IoAcquireRemoveLock的所有後續呼叫都會失敗。
IoReleaseRemoveLockAndWait 傳回之後,驅動程式應該將裝置視為處於已準備好移除的狀態,且無法執行 I/O 作業。 因此,驅動程式不得呼叫 IoInitializeRemoveLock 來重新初始化移除鎖定。 驅動程式驗證器正在驗證驅動程式時違反此規則,將會導致錯誤檢查。
因為驅動程式會將 IO_REMOVE_LOCK 結構儲存在裝置物件的裝置延伸模組中,因此當驅動程式在處理 IRP_MN_REMOVE_DEVICE 要求時刪除裝置延伸模組時,會刪除移除鎖定。