Linux中斷機制分析

FreeeLinux發表於2017-01-08

目錄

中斷的型別


中斷一般分為非同步中斷(一般由硬體引起)和同步中斷(一般由處理器本身引起)。

非同步中斷:CPU 處理中斷的時間過長,所以先將硬體復位,使硬體可以繼續做自己的工作。然後再適當時候處理中斷請求中耗時的部分。

舉個例子:網路卡的工作原理

  1. 網路卡收到資料包後,向 CPU 發出中斷訊號,請求處理接收到的資料包。
  2. CPU 將收到的資料包拷貝到記憶體後,即通知網路卡繼續工作。
  3. 至於資料包拷貝至記憶體後的處理會在適當的時候進行。

這樣做避免了處理資料包時間過長導致網路卡接收資料包速度變慢。

同步中斷:CPU 處理完中斷請求的所有工作後才反饋硬體

舉個例子:系統異常處理(比如運算中的除0操作)

  1. 應用程式出現異常後,需要核心來處理。
  2. 核心呼叫響應的異常處理函式來處理異常。
  3. 處理完後終了應用程式或者給出 message。

同步中斷應該處理很快就能完成的那種中斷。

中斷的上半部和下半部


中斷處理對處理時間要求很高,如果一箇中斷要花費較長時間,那麼中斷處理一般分為兩部分。
上半部只做一些必要的工作後,立即通知硬體自己繼續則工作。
下半部是中斷處理中耗時的部分,CPU 會在適當的時候去完成。當然這個適當的時候一般都很短。

中斷相關函式


首先說明,不同的裝置對應的中斷不同,每個中斷都通過一個唯一的數字標記。這些數字就是中斷值,又被稱為中斷請求(irq)線,有了中斷線我們就可以很容易分清誰是誰的中斷了。

響應中斷時,核心會執行一個函式,中斷處理程式 ISR,一個裝置的中斷處理程式是這個裝置驅動的一部分。

實現一箇中斷,主要需要知道 3 個函式:

  • 註冊中斷的函式
  • 釋放中斷的函式
  • 中斷處理程式的宣告

註冊中斷的函式

位置:linux/interrupt.h inclue/linux/interrupt.h

定義如下:

    /*
     * irq        - 表示要分配的中斷號
     * handler    - 實際的中斷處理回撥函式
     * flags      - 標誌位,表示此中斷具有的特性
     * name       - 中斷裝置的 ASCII 表示,這些會被 /proc/irq 和 /proc/interrupts 檔案使用
     * dev        - 用於共享中斷線,多箇中斷程式共享一箇中斷線時(意思就是共用一箇中斷號),依靠 dev 來區別各個中斷程式
     * 返回值      - 0 if success 
int request_irq(unsigned int irq, 
                irq_handler_t handler,
                unsigned long flags,
                const char* name,
                void *dev) 

這個函式可能睡眠,不允許在中斷上下文/其他不允許阻塞的程式碼中執行。

釋放中斷的函式

定義比較簡單

void free_irq(unsigned int irq, void *dev)

如果不是共享中斷線,則直接刪除 irq 對應的中斷線
如果是共享中斷線,則判斷此中斷處理程式是否是中斷線上最後一箇中斷處理程式,是就同時刪除中斷線和中斷處理程式,不是就只刪除中斷處理程式

中斷程式的宣告

宣告格式如下:

/*
 * 中斷處理程式的宣告
 * @ irq   - 中斷處理程式(即request_irq()中handler)關聯的中斷號
 * &dev    - 與 request_irq() 中的一樣,表示一個裝置的結構體,用來區別哪個裝置引發中斷
 * 返回值   - irqrenturn_t 型別,成功返回 IRQ_HANDLED 失敗返回 IRQ_NONE
 static irqreturn_t intr_handler(int, irq, void* dev);

中斷處理機制

中斷處理的過程主要涉及三個函式:

  • do_IRQ 與體系結構有關,多所接收的中斷進行應答
  • handle_IRQ_event 呼叫中斷線上所有中斷處理
  • ret_from_intr 恢復暫存器,將核心恢復到中斷前的狀態

處理流程如下:
這裡寫圖片描述

完結。

相關文章