跳至內容

延遲過程呼叫

本頁使用了標題或全文手工轉換
維基百科,自由的百科全書

延遲過程呼叫(DPC)是Microsoft Windows作業系統的機制,允許高優先級任務(如中斷處理程式英語interrupt handler)延遲所需的低優先級任務稍後執行。這使得裝置驅動程式與其他低層事件消費者更快地執行其處理的高優先級部分,排程非關鍵的附件處理稍後以較低優先級執行。

DPC是通過DPC對象實現的。當裝置驅動程式或其他內核態程式發出DPC請求時,作業系統內核建立DPC對象,投寄到DPC佇列尾部。多核處理器的每個內核有自己的DPC佇列。當Windows作業系統的IRQL降低到Dispatch/DPC級,作業系統檢查DPC佇列,逐個執行掛起的DPC,直至佇列為空或者發生IRQL更高的中斷。

例如,當時鐘中斷發生時,時鐘中斷服務程式通常增加當前線程的計數器以計算當前線程的總執行時間,把它的時間片減1。當時間片減少到0,線程排程器將被喚醒去選擇下一個在當前處理器內核上執行的線程並做線程上下文交換。時鐘中斷服務程式執行在非常高的IRQL上,它應該在稍後的IRQL下降到低階時才去執行線程排程程式。因此時鐘中斷服務程式請求一個DPC對象並把這個對象放在DPC佇列尾部,當處理器的IRQL下降到DPC/Dispatch級別時,回去執行DPC佇列中的任務。

當流音影片工作時,使用DPC處理流輸入到緩衝區的音頻。如果另外一個DPC執行了很長時間並且另一次中斷產生了新的緩衝區數據,在第一塊數據被處理前,會發生訊號缺失英語Dropout (electronics)結果。[1]

技術細節[編輯]

具體說,CPU的每個內核對應的_KPRCB數據結構中,有兩個DPC佇列:

  • (普通)DPC佇列:普通的DPC可以在任何一個線程環境中執行
  • 線程化DPC佇列:這種DPC只能在內核啟動時系統建立的一個叫做DPC的線程中執行。該線程工作在passive層,但有最高的線程優先級(Realtime級)。因此,CPU一旦工作在passive級,最先執行的就是線程化DPC常式中的代碼。

DPC執行常式一般較大,為避免當前線程的執行棧溢位,DPC常式使用每個CPU專門的DPC執行棧。

DPC有三種優先級:

  • low:入隊時放在佇列頭部,僅當佇列長度超限或者DPC請求率太低,才會被執行。
  • medium:預設值。入隊時放在佇列尾部,總是被投遞(即執行)。
  • high:入隊時放在佇列頭部,總是被投遞(即執行)。

DPC對象是Windows內核對象之一,其數據結構定義為:

Typedef struct _KDPC
{
 UCHAR Type;//DpcObject或者ThreadedDpcObject类型
 UCHAR Importance;//High,medium,low
 USHORT Number;//CPU的哪个核上
 LIST_ENTRY DpcListEntry;//链表结构
 PKDEFERRED_ROUTINE DeferredRoutine;//DPC例程
 PVOID DeferredContext;//执行DPC时的上下文 
 PVOID SystemArgument1;//执行DPC时的参数1 
 PVOID SystemArgument2;//执行DPC时的参数2 
 Volatile PVOID DpcData;//指向CPU的核的数据结构_KPRCB中的DpcData成员
}KDPC

DPC對象入隊時,內核會請求一個在Dispatch/DPC級的軟件中斷。當IRQL降低到APC或者PASSIVE級時,會投遞一個APC對象並把IRQL升到DPC級。此時DPC常式會在任何任意行程的執行環境中,因此DPC常式通常只使用內核地址空間。

裝置驅動編程[編輯]

裝置驅動編程中使用下述API來管理延遲過程呼叫:

  • IolnitimizeDpcRequest:初始化裝置對象的內建DPC對象,同時註冊一個DPC常式。由KeInitializeDpc將DPC對象與DPC常式、驅動程式建立的裝置對象聯絡起來。
  • IoRequestDpc:請求一個DPC呼叫,由KeInsertQueueDpc函數將DPC對象排隊。如果在DPC常式執行前,該裝置又生成一個中斷,系統內核將忽略隨後入隊的任何DPC對象。即每個裝置只能有一個DPC對象。
  • KeSetTargetProcessorDpc:把一個DPC對象送入特定處理器的DPC佇列
  • KeSetImportanceDpc:設置DPC對象的優先級
  • KiRetireDpcList:逐個執行DPC佇列中的所有對象

參考文獻[編輯]

  1. ^ Ute Eberhardt. DPC Latency Checker. Thesycon.de. 27 June 2012 [2012-11-07]. (原始內容存檔於2012年10月30日).