一 中斷分類
根據中斷源不同,可以將中斷分為
-
硬件中斷:硬件上產生的中斷,可以來自處理器的內部和外部。處理器的外部中斷可以來自各種PIN信號接口和Local APIC的LINT0和LINT1引腳,以及外部的I/O APIC發送過來的中斷信息。
-
軟件中斷:軟件上產生的中斷,使用INT指令主動發起的中斷,如INT 0X40,調用0X40號的中斷服務例程。
硬件中斷源又可以分為
- 可屏蔽中斷:可屏蔽的中斷如下
-
通過處理器的INTR pin接收的中斷請求,典型地,INTR連接到8259A PIC上,在支持APIC的處理器上,LINT0被作為INTR連接到外部中斷控制器上
-
通過Local APIC產生的本地中斷源
-
來自芯片組上的I/O APIC產生的中斷信息
- 不可屏蔽中斷:通過處理器NMI pin接收的中斷請求是不可屏蔽的,在支持APIC的處理器上INTR1 pin被作為NMI pin使用,接收來自外部的NMI信號
二 中斷控制器
- 以前的8259A PIC(8259可編程中斷控制器)
在單處理器上,處理器的INTR pin接收來自外部8259中斷控制器傳送過來的中斷請求,其位於PCI-to-ISA bridge(南橋)芯片的LPC控制器里。

每個8259A PIC的IR口都連接着一條IRQ線。主片的IR0到IR7對應着IRQ0到IRQ7線,但是IR2連接着從片的INTR pin。從片的IR0到IR7對應着IRQ8到IRQ15線。由於從片連接到主片的IR2上,所以從片的IR1同時連接到IRQ2和IRQ9。
在8259A中,主片IR0的中斷請求優先級最高,主片IR7最低,從片IR0-7所有中斷請求優先級都相當於IRQ2。所以IRQ線的優先級由高到低次序為IRQ0,IRQ1,IRQ8-15,IRQ3-7。
- 現在的中斷控制器:APIC
為了適應多處理器,Intel在Pentium處理器開始引入了APIC(Advanced Programmable Interupt Controller)機制。
APIC經歷了4個版本,82489DX芯片,APIC,xAPIC,x2APIC。xAPIC共有256個IRQ線,而x2APIC比xAPIC多了256個,總共512條IRQ線。

三 中斷請求級IRQL
在APCI中,每個IRQ都有各自的優先級,一個正在運行的線程可能被中斷打斷,進入到中斷處理函數,當遇到優先級更高的中斷,處在低優先級的中斷也會被打斷,進入到更高級的中斷處理函數。
windows將中斷的概念進行了擴展,提出了中斷請求級的概念,數字低的優先級高,其中不僅包括了APIC的所有中斷,也包括了3個軟件中斷。

用戶模式的代碼運行在最低優先級PASSIVE_LEVEL。驅動中的DriverEntry,派遣函數,AddDevice等函數一般運行在PASSIVE_LEVEL,在必要的時候可申請進入DISPATCH_LEVEL函數。
需要特別注意的是,windows負責線程調度的組件是運行在DISPATCH_LEVEL級別,當前的線程運行完時間片后,系統自動從PASSIVE_LEVEL級別提升到DISPATCH_LEVEL級別。當線程切換完畢后,操作系統又從DISPATCH_LEVEL降到PASSIVE_LEVEL。驅動程序的StartIO函數和DPC函數也運行在DISPATCH_LEVEL級別。在內核模式,可以通過KeGetCurrentIrpl內核函數來得到當前的IRQL級別。
四 代碼中斷級
PASSIVE_LEVEL比DISPATCH_LEVEL低,在實際編程中,許多具有比較復雜功能的內核API都要求在PASSIVE下運行,而只有比較簡單的API能在DISPATCH級執行。
在調用任何一個內核API前,必須查看WDK文檔,了解這個內核API的中斷要求
中斷級的簡單判斷方法
如何判斷我們正在編寫的代碼的中斷級呢?暫時可以使用下面規則來處理。
- 規則1:如果在調用路徑沒有特殊情況(導致中斷級的提高或降低),則一個函數的中斷級與調用源的中斷級相同;
- 規則2:如果在調用路徑上有獲取自旋鎖,則中斷級隨之升高;如果有釋放自旋鎖,則中斷級隨之降低。
如果當前代碼運行在DISPATCH級,而我們又必須調用PASSIVE級的內核API,使用內核API強制降低當前的中斷請求級是不被允許的,windows的代碼都運行在規范的中斷級上,任意降低中斷級都會導致不可預料的后果。
這樣的問題有很多種解決方法,比如生成一個專門的線程去執行PASSIVE級的代碼。