天天看點

DPC

DeferredProcecure Call,延遲過程調用。是一種執行在任意線程上下文的DISPATCH_LEVEL層的可執行例程。硬體中斷使用他們處理來自裝置的中斷。硬體驅動這樣做是因為ISR通常運作在更高IRQLs(高于DISPATCH_LEVEL),如果他們花費太長時間,可能會降低系統的整體性能。是以,ISR典型的隊列一個DPC并且馬上傳回,是以系統可以處理其它的中斷請求。軟驅動能使用DPCs快速的執行短任務。

DPC的用法很簡單:用KeInitializeDpc來初始化一個KDPC對象,然後用KeInsertQueueDpc來隊列他們。當處理器的IRQL從高優先級降到DISPATCH_LEVEL時,核心處理所有在隊列中的DPCs。

每一個CPU保持着他們自己擁有的DPC隊列。這個隊列存放在CPU相關的KPRCB結構體中。一個是普通的DPC隊列,另外一個是線程DPC隊列。

Windows有一些機制來處理DPC。如KiIdleLoop、CPU處于DISPATCH_LEVEL或者在系統初始化的一個線程裡(KiStartDpcThread)。

運作在DISPATCH_LEVEL這個IRQL上的線程不能被其它軟中斷(低于DISPATCH_LEVEL)打斷。換句話說,如果在DPC例程裡有一個死循環,和它相關的CPU便會一直自旋,使得系統看起來好像被當機了。在多處理器上,或許不會被當機但是執行這個DPC的處理器将不能被線程排程器使用。另外,DPC例程中不能等待任何的可分發對象,因為這些分發對象他們自己就運作在DISPATCH_LEVEL,這就是為什麼相KeWaitForSingleObject和KeDelayExecuteThread不能在DPC例程中被調用的原因。

Windows有運作在特定時間周期的DPC看門狗例程用來檢測DPC,bugchecks是DPC_WATCHDOG_VIOLATION(0x133)。可以用KeQueryDpcWatchdogInformation來查詢這個看門狗的周期。

一些RootKits用DPC來同步通路全局連結清單。例如,可以從ActiveProcessLinks中移除一個實體來隐藏程序。因為這個連結清單能被任意處理器在任何時候修改,一些RootKits作者使用DPC連同其它同步機制來安全的處理這個問題。

繼續閱讀