關于中斷處理程序和中斷服務例程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; ? ?
?????? 首先中斷處理程序(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; ? ?
轉自:http://blog.chinaunix.net/uid-27177626-id-3438994.html