關於
中斷處理程序和
中斷服務例程ISR的區別及聯繫,以前一直搞混,今天抽時間將二者關係弄弄清楚。ok,下面進入主題。
首先
中斷處理程序(
Interrupt Handler)和
中斷服務例程ISR(Inerrupt Service Routine)是兩個不一樣的概念.
簡單來講就是,一條中斷線對應一箇中斷處理程序,而一箇中斷處理程序再對應若干個中斷服務例程,具體看下圖所示:
從上圖中能很直觀的看出全部的中斷服務例程掛在中斷請求隊列中,這個工做是由request_irq()函數來完成的,其實也就是對中斷服務例程進行註冊,關於這個函數的具體實如今include/linux/interrupt.h中。而中斷處理程序就至關於某個中斷向量的總的處理程序,好比上圖中IRQ0x09_interrupt()是中斷號爲9(向量爲47)的總處理程序,假如這個9號中斷由5個設備共享,那麼這5個設備都分別有其對應的中斷服務例程。
也就是說當有多個設備須要共享某個中斷線時,中斷處理程序必需要調用ISR,此時會調用handle_IRQ_event()
來運行掛在該中斷線上的全部中斷服務例程,下圖給出了具體的調用關係:
這其實就是中斷處理程序的執行過程。其中IRQn_interrupt表示從IRQ0x00_interrupt到IRQ0x0f_interrupt的任意一箇中斷處理程序。這個中斷處理程序須要調用do_IRQ()函數,而do_IRQ()函數對收到的中斷請求進行應答,並禁止這條中斷線,而後要確保這條中斷線上有一個有效的中斷服務例程,並且目前這個這個中斷服務例程已經啓動但未執行。這時do_IRQ()調用handle_IRQ_event()來運行掛在這條中斷線上的全部中斷服務例程。
最後再補充說明一下在內核中用於讓多個設備共享一條中斷線而設置的數據結構irqaction(3.7版本的內核):
typedef
irqreturn_t (*
irq_handler_t)(int, void *); //聲明一箇中斷服務例程的鉤子函數,返回值爲irqreturn_tx型
struct
irqaction {
irq_handler_t
handler; //指向一個具體的I/O設備的中斷服務程序
void *
dev_id; //指定的I/O設備的主設備號和次設備號
void
__percpu *
percpu_dev_id; //用於識別不一樣cpu設備的資料
struct
irqaction *
next; //指向用於共享中斷線的下一個irqaction結構
irq_handler_t
thread_fn; //指向一個具體的線程化中斷的中斷服務例程
struct
task_struct *
thread; //指向線程中斷的線程指針
unsigned int
irq; //所申請的中斷號
unsigned int
flags; //一組用於描述中斷線與I/O設備之間關係的中斷標誌
unsigned long
thread_flags; //用於描述線程中斷的中斷標誌
unsigned long
thread_mask; //中斷掩碼
const char *
name; //中斷設備名稱
struct
proc_dir_entry *
dir; //指向IRQn相關的/proc/irq/n目錄的描述符
}
____cacheline_internodealigned_in_smp;