[中斷概述]
中斷本質上是一種特殊的電信號,由硬件設備發向處理器。異常和中斷的不同是異常在產生時必須考慮與處理器時鐘同步。實際上異常也常常稱為同步中斷。比如在除0或者缺頁時,必須靠內核處理的時候,處理器就會產生一個異常。
[中斷處理機制的實現]
中斷從硬件到內核的路由
設備產生中斷,通過總線把電信號發送給中斷控制器。如果中斷線是激活的(它們允許被屏蔽的),那麼中斷控制器就會把中斷發往處理器。在大多數體系結構中,這個工作就是通過電信號給處理器的特定管腳發送一個信號。除非在處理器上禁止該中斷,否則處理器會立即停止它正在做的事,關閉中斷系統,然後跳到內存中預定的位置開始執行那裡的代碼。這個預定義的位置是由內核設置的,是中斷處理程序的入口點。
[中斷處理程序]
在響應一個特定中斷的時候,內核會執行一個函數,該函數叫做中斷處理程序(interrupt handler)也叫做中斷服務例程(interrupt service routine)。
中斷處理程序就是一個普普通通的C函數,但是它與其他內核函數的真正區別在於,中斷處理程序時被內核調用來響應中斷的,它運行於中斷上下文中。
注冊中斷處理程序:
static inline int __must_check
request_irq(unsigned int irq, irq_handler_thandler, unsigned long flags,
const char *name, void *dev)
irq:分配的中斷號
handler:中斷處理函數程序的指針 typedefirqreturn_t (*irq_handler_t)(int, void *);
flags:中斷類型
name:與中斷相關的設備的名字;
dev:用於共享中斷,因為可能在一條中斷線上有幾個設備,dev用來區分是哪個設備產生的中斷
中斷上下文和進程上下文對比
中斷上下文
進程上下文
定義
當執行一個中斷處理程序時,內核處於中斷上下文中
當程序調用了系統調用或者觸發了某個異常,它就陷入了內核空間,此時,內核代表進程執行並處於進程上下文中。
睡眠情況
不可睡眠,不能被調度,也就是說中斷上下文中不能使用有可能睡眠的函數
可睡眠,可調度
同步機制
自旋鎖
都可
[中斷上半部和下半部]
首先問自己一個問題,為什麼要把中斷分為上半部和下半部,難道一個就放在中斷處理程序中不好嗎?答案是否定的
1、中斷可以隨時的打斷其他正在執行的程序,如果被打斷的代碼對系統很重要,那麼此時中斷處理程序的執行時間應該是越短越好;
2、中斷處理程序正在執行時,會屏蔽同條中斷線上的中斷請求;而更嚴重的是,如果設置了IRQF_DISABLED,那麼該中斷服務程序執行時會屏蔽所有其他的中斷請求。那麼此時應該讓中斷處理程序執行的越快越好。
上半部:一個快速、異步而簡單的處理程序專門來負責對硬件的中斷請求做出快速響應,與此同時也要完成那麼些對時間要求很嚴格的操作;
下半部:那麼對時間要求相對寬松,其他的剩余工作會在稍後的任意時間執行。
下面是對上半部和下半部的工作劃分:
如果一個任務對時間非常敏感,將其放在中斷處理程序中執行;
如果一個任務中和硬件相關,將其放在中斷處理程序中執行;
如果一個任務要保證不被其他中斷(特別是相同的中斷)打斷,將其放在中斷處理程序執行;
其他所有任務,都應考慮放在下半部執行。
[下半部機制]
軟中斷
軟中斷保留給系統中對時間要求最嚴格以及最重要的下半部使用,目前只有兩個子系統(網絡和scsi)直接使用軟中斷。
Tasklet
Tasklet是利用軟中斷實現的一種下半部機制。在選擇使用軟中斷還是tasklet時,建議使用tasklet,除了網絡和SCSI情況。相比軟中斷,tasklet的接口更簡單,鎖保護要求較低。
工作隊列
工作隊列是可以把工作推後交由一個內核線程去執行,下半部總是會在進程上下文中執行,允許重新調度和睡眠。
三種下半部機制對比
下半部
上下文
順序執行保障
軟中斷
中斷
沒有
Tasklet
中斷
同類型不能同時執行
工作隊列
進程
沒有(和進程上下文一樣被調度)