爲什麼需要中斷?
1)外設的處理速度一般慢於CPU
2)CPU不能一直等待外部事件
所以設備必須有一種方法來通知CPU它的工作進度,這種方法就是中斷。
2、 中斷實現
在Linux驅動程序中,爲設備實現一箇中斷包含兩個步驟:
1)向內核註冊中斷
2)實現中斷處理函數
3、 中斷註冊
request_irq用於實現中斷的註冊功能:
int request_irq(unsigned int irq, void (*handler)(int, void*, struct pt_regs *), unsigned long flags, const char *devname, void *dev_id)
返回0表示成功,或者返回一個錯誤碼
中斷註冊(參數)
1) unsigned int irq 中斷號。
2)void (*handler)(int,void *,struct pt_regs *) 中斷處理函數。
3)unsigned long flags 與中斷管理有關的各種選項。
4)const char * devname 設備名
5)void *dev_id 共享中斷時使用。
a)中斷註冊(中斷標誌)
在flags參數中,可以選擇一些與中斷管理有關的選項,如:
1)IRQF_DISABLED(SA_INTERRUPT)
如果設置該位,表示是一個“快速”中斷處理程序;如果沒有設置這位,那麼是一個“慢速”中斷處理程序。
2)IRQF_SHARED(SA_SHIRQ)
該位表明中斷可以在設備間共享。
b)快速/慢速中斷
這兩種類型的中斷處理程序的主要區別在於:快速中斷保證中斷處理的原子性(不被打斷),而慢速中斷則不保證。換句話說,也就是“開啓中斷”標誌位(處理器IF)在運行快速中斷處理程序時是關閉的,因此在服務該中斷時,不會被其他類型的中斷打斷;而調用慢速中斷處理時,其它類型的中斷仍可以得到服務。
c) 共享中斷
共享中斷就是將不同的設備掛到同一個中斷信號線上。Linux對共享的支持主要是爲PCI設備服務。共享中斷也是通過request_irq函數來註冊的,但有三個特別之處:
1)申請共享中斷時,必須在flags參數中指定 IRQF_SHARED位
2)dev_id參數必須是唯一的。
3)共享中斷的處理程序中,不能使用disable_irq(unsigned int irq) 爲什麼? 如果使用了這個函數,共享中斷信號線的其它設備將同樣無法使用中斷,也就無法正常工作了。
4、 中斷處理程序
什麼是中斷處理程序,有何特別之處?中斷處理程序就是普通的C代碼。特別之處在於中斷處理程序是在中斷上下文中運行的,它的行爲受到某些限制:
1) 不能向用戶空間發送或接受數據
2) 不能使用可能引起阻塞的函數
3) 不能使用可能引起調度的函數
5、 中斷處理函數流程
{
/* 判斷是否是本設備產生了中斷(爲什麼要做這樣的檢測?) */
value = inb(short_base);
if (!(value & 0x80)) return;
/* 清除中斷位(如果設備支持自動清除,則不需要這步) */
outb(value & 0x7F, short_base);
/* 中斷處理,通常是數據接收 */
。。。。。。。。。
/* 喚醒等待數據的進程 */
wake_up_interruptible(&short_queue);
6、 釋放中斷
當設備不再需要使用中斷時(通常在驅動卸載時), 應當把它們返還給系統,使用:void free_irq(unsigned int irq, void *dev_id)