本文轉帖於:http://blog.csdn.net/swt914/article/details/6574458
Kernel 中斷處理圖
1. Linux 定義了名字為irq_desc 的中斷常式描述符表:(include/linux/irq.h)
struct irqdesc irq_desc[NR_IRQS];
NR_IRQS 表示中斷源的數目。
2. irq_desc []是一個指向irq_desc_t 結構的數組, irq_desc_t 結構是各個裝置插斷服務常式的描述符。Irq_desc_t 結構體中的成員action 指向該中斷號對應的irqaction 結構體鏈表。Irqaction 結構體定義如下:
/* include/linux/interrupt.h */ struct irqaction { irq_handler_t handler; /* 指向中斷服務程式 */ unsigned long flags; /* 中斷標誌 */ unsigned long mask; /* 中斷掩碼 */ const char * name; /* I/O裝置名稱 void *dev_id; /* 裝置標識 */ struct irqaction * next; /* 指向下一個描述符 */ int irq; /* IRQ線 */ struct proc_dir_entry * dir; /* 指向IRQn相關的/proc/irq/n目錄的描述符 */ } ;
|
其中關鍵的handler 成員指向了該裝置的中斷服務程式,由執行request_irq 時建立。
3. 在驅動程式初始化時,若使用到中斷,通常調用函數 request_irq ()建立該驅動程式對應的 irqaction 結構體,並把它登記到 irq_desc [irq_num]->action 鏈表中。 Iqr_num 為驅動程式申請的中斷號。
request_irq ()函數的原型如下:
/* kernel/irq/manage.c */ int request_irq( unsigned int irq, irqreturn_t ( * handler) ( int , void * , struct pt_regs * ) , unsigned long irqflags, const char * devname, void * dev_id) ;
|
參數 irq 是裝置中斷求號,在向 irq_desc [] 數組登記時,它做為數組的下標。把中斷號為 irq 的 irqaction 結構體的首地址寫入 irq_desc [irq]->action 。這樣就把裝置的插斷要求號與該裝置的插斷服務常式 irqaction 聯絡在一起了。
這樣當 CPU 接收到插斷要求後,就可以根據中斷號通過 irq_desc [] 找到該裝置的中斷服務程式。流程如所示。
4. 關於共用中斷
共用中斷的不同裝置的 iqraction 結構體都會添加進該中斷號對應的 irq_desc 結構體的 action 成員所指向的 irqaction 鏈表內。當核心發生中斷時,它會依次調用該鏈表內所有的 handler 函數。因此,若驅動程式需要使用共用中斷機制,其中斷處理函數必須有能力識別是否是自己的硬體產生了中斷。通常是通過讀取該硬體裝置提供的中斷 flag 標誌位進行判斷