一、安裝中斷處理
1. 申請中斷
int request_irq(unsigned int irq,
irqreturn_t (*handler)(int, void *, struct pt_regs *),
unsigned long flags,
const char *dev_name,
void *dev_id);
/*
申請中斷通道(成功傳回0)
irq中斷号;handler中斷處理函數的指針;flag與中斷管理有關的位掩碼;
dev_id用于共享的中斷信号線,可用于指向驅動程式自己的私有資料區,用來識别裝置
*/
void free_irq(unsigned int irq, void *dev_id);
int can_request_irq(unsigned int irq, unsigned long flags);
/* 查詢某個中斷線是否可用,可用傳回非零 */
flags:
SA_INTERRUPT:快速中斷處理例程,運作于中斷的禁用狀态下(目前處理器上的其他所有中斷都被禁止)
SA_SHIRQ:中斷可在裝置間共享
SA_SAMPLE_RANDOM:中斷能對/dev/random裝置和/dev/urandom裝置使用的熵池(entropy pool)有貢獻。熵池用來收集來自裝置驅動程式和其它來源的環境噪音。add_interrupt_randomness()函數利用裝置兩次中斷的間隔時間作為噪聲源将随機資料加入熵池。
2. /proc接口
/proc/interrupt:硬體中斷産生時内部計數器遞增,産生的報告顯示在/proc/interrupt,隻顯示已安裝了中斷處理例程的中斷,且在檔案快照時沒使用的話也不會出現。不依賴于體系結構。
/proc/stat:記錄了一些系統活動的底層統計資訊(包括從系統啟動開始接收到的中斷數量)。所有中斷線都會顯示,字段的數量依賴于核心之下的硬體。
3. 自動檢測IRQ号
有些裝置(如PCI标準)會聲明打算使用的中斷線,而另一些裝置則需自動檢測進行一些探測工作,決定使用哪條IRQ以便正确安裝處理例程。
裝載時配置設定中斷号:insmod xxx.ko irq=x
核心輔助函數:
//1.配置設定中斷的位掩碼
unsigned long probe_irq_on(void);
/* 需儲存傳回的位掩碼,且調用後需至少産生一次中斷再調用下一個函數 */
//2.裝置産生中斷
//3.适當延時(留給中斷探測)
//4.傳回上述産生中斷的編号
int probe_irq_off(unsigned long);
/* 若無中斷發生則傳回0,若産生了多次中斷則傳回負值 */
DIY探測:
啟用所有未被占用的中斷,觀察會發生什麼(若不能預知可能的IRQ值,則需要探測0 - NR_IRQS-1所有中斷)
二、中斷處理例程
1. 限制
不是在程序上下文運作,是以不能向空間發送或接收資料,不能休眠(wait_event、使用不帶GFP_ATOMIC的記憶體配置設定操作、鎖住一個信号量),不能調用schdule函數
2. 功能
将有關中斷接收的資訊回報給裝置,根據中斷不同含義對資料進行讀寫
清除中斷挂起位(有些裝置沒有,可在第一步也可在最後執行)
通知程序事件已經發生(喚醒在該裝置上休眠的程序)
static irqreturn_t sample_interrupt(int irq, void *dev_id, struct pt_regs *regs)
/*
中斷處理例程
irq:中斷号
dev_id:區分共享中斷線上的不同裝置(中斷處理程式)?
regs:可有可無?儲存了處理器進入中斷前的環境?
*/
傳回值:irqreturn_t:IRQ_HANDLED(确實需要處理);IRQ_NONE
也可以用宏來産生傳回值:IRQ_RETVAL(handled),如果需要處理該中斷,則handled取非零,給核心使用以抑制假中斷
3. 啟用和禁用中斷
void disable_irq(int irq);//禁用中斷線,可嵌套調用,會等待正在執行的處理例程完成
void disable_irq_nosync(int irq);//立即傳回,但可能會導緻競态
void enable_irq(int irq);//啟用
void local_irq_save(unsigned long flags);
void local_irq_disable(void);
void local_irq_restore(unsigned long flags);
void local_irq_enable(void);
/* 禁用和啟動所有中斷 */
三、頂半部和底半部(上半部和下半部)
頂半部:中斷處理例程
底半部:tasklet、工作隊列