拋棄中斷bottom half,使用中斷線程吧

在linux裏,中斷處理分爲頂半(top half),底半(bottomhalf),在頂半里處理優先級比較高的事情,要求佔用中斷時間儘量的短,在處理完成後,就激活底半,有底半處理其餘任務。底半的處理方式主要有soft_irq,tasklet,workqueue三種,他們在使用方式和適用情況上各有不同。soft_irq用在對底半執行時間要求比較緊急或者非常重要的場合,主要爲一些subsystem用,一般driver基本上用不上。tasklet和work queue在普通的driver裏用的相對較多,主要區別是tasklet是在中斷上下文執行,而workqueue是在process上下文,因此可以執行可能sleep的操作。
2.6.30裏,在ingo molnar的RT tree裏存在有一段時間的interruptthread終於merge到mainline了。此時如果使用request_threaded_irq申請的中斷,handler不是在中斷上下文裏執行,而是在新創建的線程裏執行,這樣,該handler非常像執行workqueue,擁有所有workqueue的特性,但是省掉了創建,初始化,調度workqueue的繁多步驟。處理起來非常簡單。讓我們看看這個接口:
int request_threaded_irq(unsigned int irq, irq_handler_t handler, irq_handler_t thread_fn, unsigned long irqflags, const char *devname, void *dev_id)

和request_irq非常類似,irq是中斷號, handler是在發生中斷時,首先要執行的code,非常類似於頂半,該函數最後會return IRQ_WAKE_THREAD來喚醒中斷線程,一般設爲NULL,用系統提供的默認處理。thread_fn,是要在線程裏執行的handler,非常類似於底半。 後三個參數基本和request_irq相同。irqsflags新增加了一個標誌,IRQF_ONESHOT,用來標明是在中斷線程執行完後在打開該中斷,該標誌非常有用,否則中斷有可能一直在頂半執行,而不能處理中斷線程。例如對於gpio level中斷,如果不設置該位,在頂半執行完成後,會打開中斷,此時由於電平沒有變化,馬上有執行中斷,永遠沒有機會處理線程。

下邊一個實際例子來說明它的應用。在手機平臺中,檢測耳機的插入一般是通過耳機插孔中機械變化導致一個baseband gpio的電平的變化,在該gpio中斷裏進行耳機插入處理。但是耳機插入一般都有個抖動的過程,需要消抖處理。最簡單的辦法是在中斷髮生後,延時一段時間(例如200ms),然後再檢查GPIO狀態是否穩定來確定是否有效插入。如果用老的中斷方式,不得不用workqueue的方式,你需要在頂半里激活一個delay 200ms的workqueue,然後在workqueue裏檢查。用線程化的處理方式,你僅僅需要在thread_fn裏sleep 200ms,然後在檢查即可。看,事情就這麼簡單!
發佈了13 篇原創文章 · 獲贊 4 · 訪問量 36萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章