1. 程式人生 > >內核中的中斷處理模型

內核中的中斷處理模型

自己 small 一個 status 進行 地址 clu ffi conf

內核版本: Linux 2.6.19

Kernel中斷處理模型結構圖如下:

技術分享

下面簡單介紹一下:

1. Linux定義了名字為irq_desc的中斷例程描述符表:(include/linux/irq.h)

struct irqdesc irq_desc[NR_IRQS];

NR_IRQS表示中斷源的數目。

2. irq_desc[]是一個指向irq_desc結構的數組, irq_desc結構是各個設備中斷服務例程的描述符。

struct irq_desc {
irq_flow_handler_t handle_irq;
struct irq_chip *chip;
void

*handler_data;
void *chip_data;
struct irqaction *action;
unsigned int status;

unsigned int depth;
unsigned int wake_depth;
unsigned int irq_count;
unsigned int irqs_unhandled;
spinlock_t lock;
#ifdef CONFIG_SMP
cpumask_t affinity;
unsigned int

cpu;
#endif
#if defined(CONFIG_GENERIC_PENDING_IRQ) || defined(CONFIG_IRQBALANCE)
cpumask_t pending_mask;
#endif
#ifdef CONFIG_PROC_FS
struct proc_dir_entry *dir;
#endif
const char *name;
} ____cacheline_aligned;

Irq_desc結構體中的成員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標誌位進行判斷。

內核中的中斷處理模型