當驅動程序處理IRP的時候,它可能立刻完成,也可能在中斷里才能完成,比如說,往硬件設備發出一個請求(通??梢允菍慖/O port),當設備完成操作的時候會觸發一個中斷,然后在中斷處理函數里得到操作結果。Windows有兩類中斷,硬件設備的中斷和軟中斷,分成若干個不同的優先級(IRQL)。軟中斷主要有兩種:DPC(Delayed Procedure Call)和APC(Asynchronous Procedure Call),都處于較低的優先級。驅動程序可以為硬件中斷注冊ISR(Interrupt Service Routine),一般就是修改IDT某個條目的入口。同樣,操作系統也會為DPC和APC注冊適當的中斷處理例程(也是在IDT中)。值得指出的是,DPC是跟處理器相關的,每個處理器會有一個DPC隊列,而APC是跟線程相關的,每個線程會有它的APC隊列(實際上包括一個Kernel APC隊列和User APC隊列,它們的調度策略有所區別),可以想象,APC并不算嚴格意義上的中斷,因為中斷可能發生在任何一個線程的上下文中,它被稱為中斷,主要是因為IRQL的提升(從PASSIVE到APC),APC的調度一般在線程切換等等情形下進行。當中斷發生的時候,操作系統會調用中斷處理例程,對于硬件設備的ISR,一般處理是關設備中斷,發出一個DPC請求,然后返回。不在設備的中斷處理中使用太多的CPU時間,主要考慮是否則可能丟失別的中斷。由于硬件設備中斷的IRQL比DPC中斷的高,所以在ISR里面DPC會阻塞,直到ISR返回IRQL回到較低的水平,才會觸發DPC中斷,在DPC中斷里執行從硬件設備讀取數據以及重新請求、開中斷等操作。ISR或者DPC可能在任何被中斷的線程上下文(arbitrary thread context)執行,事實上線程的上下文是不可見的,可以認為是系統借用一下時間片而已。
       總的來說,Windows的異步I/O架構中,主要有兩種動力,一是發起請求的線程,一部分內核代碼會在這個線程上下文執行,二是ISR和DPC,這部分內核代碼會在中斷里完成,可能使用任何一個線程的上下文。而調度常見使用回調和事件(KEVENT),比如說在往下一層的驅動程序發出請求的時候,可以指定一個完成例程Completion Routine,當下層的驅動完成這個請求的時候會調用這個例程,而往往在這個例程里,就是簡單的觸發一下一個事件。
      另外可以順便提一下Linux。Linux 2.6也有類似的中斷機制,它有更多的軟中斷優先級,即不同優先級的softirq,而類似于DPC,Linux也提供了專門的軟中斷,對應DPC的就是tasklet。Linux沒有一個像windows這么一致的層次驅動程序架構,所以它的異步I/O稍微粗糙一些,主要是通過以前的一些阻塞點,現在直接返回-EIOCBRETRY,而讓調用者在合適的時機繼續重試。在這個方法中,可以認為整個操作由一個函數完成,每次操作有進展時,都把這個函數從頭執行一遍,當然已經完成的部分就不會再有實際的I/O。這樣的最大好處是原有的文件系統和驅動程序不用完全重寫。而對于同步調用,只要阻塞就可以了,這樣對系統的修改較小。這時候,要提供POSIX aio的語義,就可能需要提供一些用戶線程來完成重試的過程了(回想Windows可以通過中斷和DPC完成的)。而對于Solaris,也是類似的處理,如果設備支持異步I/O,那就通過中斷可以完成,否則就使用內部的LWP來模擬。

                以上內容摘自 http://blog.csdn.net/emag_cpp/archive/2005/02/01/276301.aspx