|
Linux下面的中斷分兩種: 同步的中斷,也稱為異常,之所以稱為"同步",是因為這些異常是在程序執行的時候某條語句觸發的,比如除0錯誤,缺頁異常等等,有名的段錯誤也屬于其中的一種,這個時候,你的程序不能繼續往下走,而必須對這些異常做出回應,也就是處理. 異步的中斷,也就是中斷,之所以稱為"異步",是因為這些中斷是在當前指令之外的指令觸發的.比如你的程序正在執行,來了一個I/O請求,或者定時器到時間被觸發了,等等.也就是說,程序無法預知中斷在什么時候到來.
有點兒亂了,小結一下:中斷分為兩種,同步的中斷叫做異常,一般由程序中的錯誤觸發;異步的中斷叫做中斷,一般由當前程序外部觸發,比如IO請求,定時器等觸發.
每一個中斷與一根IRQ線(Interrupt ReQuest (IRQ) line)對應,而IRQ是連接到可編程中斷控制器(Programmable Interrupt Controller,簡稱PIC)上的.它完成下面的工作: 1) 檢查與之相連的IRQ,看看哪個IRQ被觸發了,選擇最小的被觸發的IRQ. 2) 將被中斷的IRQ轉換為一個中斷向量 3) 將中斷向量存放在IO端口,CPU可以通過數據線讀取該中斷向量 4) 發出INTR指令,告訴CPU:有一條中斷被觸發了 5) 在以上步驟之后,PIC等待CPU對這個中斷做出響應,這段時間內PIC不會去檢查新的中斷.當CPU處理完這個中斷后,PIC再去清空INTR線以接收新的中斷. 6) 重復第一步
以上是PIC所做的,簡單的說:監控IRQ,將被觸發的IRQ轉換為中斷向量,然后通知CPU.
下面來看看CPU的控制單元是怎么做的.
<<深入理解Linux內核>>中對這部分說的比較詳細了(4.2.4節),下面做一點輔助解釋性的說明: 1) 首先,每個中斷向量都與與之對應的處理程序,可以簡單的理解為,這是一個大的數組,數組索引是中斷向量,而存放的元素是函數指針,也就是對這些中斷進行處理的函數.在系統初始化的時候初始化每個中斷向量的處理函數.
2) 書中的一段話,看著有點兒令人費解的:Before dealing with that instruction, the control unit checks whether an
interrupt or an exception occurred while the control unit executed the previous
instruction. 實際上,這個查詢操作對程序來說是透明的,是CPU的控制單元自己去做的事情,如果查詢到了有中斷被觸發,再去調用上面已經注冊的處理函數.至于每次執行指令之前是怎么做到高效查找的,我不清楚,哪位知道的麻煩告知一下.
3)中斷向量的分類為: 從0~31的向量對應于異常和非屏蔽中斷。
從32~47的向量(即由I/O設備引起的中斷)分配給屏蔽中斷。
剩余的從48~255的向量用來標識軟中斷。Linux只用了其中的一個(即128或0x80向量)用來實現系統調用。當用戶態下的進程執行一條int 0x80匯編指令時,CPU就切換到內核態,并開始執行system_call( )內核函數
4) 由于中斷被觸發時需要保護現場,所以在發生中斷調用處理函數之前需要保護現場,也就是一些寄存器指針;而中斷處理完畢后需要恢復現場,因此需要將這些寄存器恢復.當然,在切換的時候,還需要考慮程序的運行權限等等.
以上就是對中斷和異常處理的大體流程.
|