什么是中斷
計算機中的“中斷”(Interruption),廣義上理解,是指打斷(interrupt)正在執行的程序使得處理器去執行其他程序。(BTW:“中斷”一詞,聽上去莫名其妙,感覺叫“打斷”更貼切,只不過有點難聽。。。)
整個操作系統就是一個中斷驅動的死循環,操作系統原理如果用一行代碼解釋,下面這樣再合適不過了。
while(true) { doNothing(); }
其他所有事情都是由操作系統提前注冊的中斷機制和其對應的中斷處理函數完成,我們點擊一下鼠標,敲擊一下鍵盤,執行一個程序,都是用中斷的方式來通知操作系統幫我們處理這些事件,當沒有任何中斷事件時,它就乖乖停在死循環里不出來。
所以,中斷,非常重要,它也是理解整個操作系統的根基。
Linux 操作系統中大多數設備都采用中斷處理方式來控制數據 I/O 。
打斷程序執行的方式
總結——硬中斷和軟中斷
從中斷實現的角度看,分為硬中斷和軟中斷。
硬中斷:由硬件CPU實現。
實現:CPU 在每個指令周期的最后,會留一個 CPU 周期去查看是否有中斷信號,若有,則把中斷號取出、去中斷向量表中尋找中斷處理程序、跳過去執行。
觸發:外部硬件直接給CPU引腳發送中斷號信息,從而引起中斷。
分類:根據硬中斷觸發的方式的不同,硬中斷可進一步分類:直接給CPU INTR引腳發信號觸發中斷、CPU自身執行指令觸發中斷、軟件通過int n等指令觸發中斷。詳見后文。
軟中斷:完全由軟件實現。
實現:OS有一個單獨的守護進程,不斷輪詢內存中的一組標志位(如BitMap),如果哪個標志位有值了,那去這個標志位對應的軟中斷向量表數組的相應位置,找到軟中斷處理函數,然后跳過去執行。
觸發:其他軟件通過設置這些標記位觸發中斷。
相關源碼:
asmlinkage void __init start_kernel(void) { ... trap_init(); sched_init(); time_init(); ... rest_init(); } static void rest_init(void) { kernel_thread(init, NULL, CLONE_KERNEL); } static int init(void * unused) { do_pre_smp_initcalls(); } static void do_pre_smp_initcalls(void) { spawn_ksoftirqd(); } // spawn kernel soft irt daemon 創建內核軟中斷守護進程 __init int spawn_ksoftirqd(void) { cpu_callback(&cpu_nfb, CPU_ONLINE, (void *)(long)smp_processor_id()); register_cpu_notifier(&cpu_nfb); return 0; } static int __devinit cpu_callback(...) { kernel_thread(ksoftirqd, hcpu, CLONE_KERNEL); } static int ksoftirqd(void * __bind_cpu) { for (;;) { while (local_softirq_pending()) { do_softirq(); cond_resched(); } } } asmlinkage void do_softirq(void) { h = softirq_vec;//軟中斷列表首地址 pending = local_softirq_pending(); //軟中斷標記字,int 32類型 do { if (pending & 1) { h->action(h);//執行中斷處理程序 h++; pending >>= 1; } while (pending); }
兩者的實現機制和觸發機制不同。但目的和最終效果一樣:都是為了產生一個信號,從而讓CPU暫止當前正在運行的程序、轉而去執行中斷處理程序、執行完之后再返回繼續執行原程序。
Linux 會把中斷分成上下兩半部分執行,上半部分用硬中斷處理最簡單的邏輯(通常是改標記位觸發軟中斷),下半部分異步執行軟中斷處理函數。因為對於耗時操作(如接收網絡數據),如果完全由硬中斷處理會影響對其他硬中斷的響應。
硬中斷的分類
Intel手冊中說明的打斷程序運行的機制


總結
這些硬中斷方式都可以打斷程序或任務的執行,它們的觸發都是為了給CPU一個中斷信號,且CPU收到信號后的后續處理流程一樣——即暫停執行當前程序或任務、根據中斷號去中斷表中找到對應的中斷處理程序並執行、執行完后返回繼續執行原程序或任務。
從硬中斷觸發的角度看,硬中斷可進一步分類:
一種分類方式,分為三類:前兩者為硬件中斷(硬件產生的中斷)、第三個為軟件中斷(軟件產生的中斷);第一者為外部中斷、后兩者為內部中斷。
Interrupt —— 外部設備通過CPU引腳觸發:可進一步分為可屏蔽中斷(連接CPU INTR引腳觸發)和不可屏蔽中斷(連接CPU NMI引腳觸發)。
An interrupt is an asynchronous event that is typically triggered by an I/O device.
INTR:硬盤、鼠標、打印機、網卡等設備發出的中斷信號,可通過 eflags 寄存器的 IF 位將所有這些外部設備的中斷屏蔽。
NMI:電源掉電、內存讀寫錯誤、總線奇偶校驗錯誤等災難性的錯誤,不可屏蔽,CPU 必須立刻處理。
Exception —— CPU執行出現異常時觸發:CPU執行指令時產生的異常引起。如除法指令分母為0、未定義的指令分別引起0、6 號中斷。分為三類:
An exception is a synchronous event that is generated when the processor detects one or more predefined conditions while executing an instruction.
Fault(故障):可恢復的錯誤。發生此中斷時,CPU 將機器狀態恢復到異常之前的狀態,之后調用中斷處理程序,結束后返回。常見的如缺頁異常。
Trap(陷阱):有意的異常。通常是調試程序中用 int3 指令主動觸發。
Abort(終止):不可恢復的異常。直接將此程序從進程表中去掉。
通過軟件(通常是系統調用)觸發:由程序或任務顯式通過 INT n 等指令觸發。
int 3:中斷向量號3,調試斷點指令
into:中斷向量號4,中斷溢出指令
bound:中斷向量號5,檢查數組索引越界指令
ud2:中斷向量號6,未定義指令,常用於軟件測試中主動發起這個中斷
注:上面所述中,硬中斷和硬件中斷(類似地,軟中斷和軟件中斷)不是一個事,前者從實現的角度說的,指用硬件實現的中斷;后者從觸發的角度說的,指通過硬件觸發的中斷。實際中需結合語境判斷,或者為了避免歧義,最好指出是從中斷實現還是中斷觸發哪個角度而言的。
參考資料
