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

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