linux中斷處理原理分析

2021-07-05 02:09:57 字數 3739 閱讀 9488

首先需要了解一下中斷的概念:乙個「中斷」僅僅是乙個訊號,當硬體需要獲得處理器對它的關注時,就可以傳送這個訊號。核心維護了乙個中斷訊號線的登錄檔,該登錄檔類似於i/o埠的登錄檔。

模組在使用中斷前要先請求乙個中斷通道(或中斷請求irq),然後在使用後釋放該通道。用到的api就是request_irq()以及free_irq()。注意在呼叫request_irq()和free_irq()的時機最好是在裝置第一次開啟和最後一次關閉之後。

對於中斷處理例程來講,它的乙個典型的任務就是:如果中斷通知程序所等待的事件已經發生,比如新的資料到達就會喚醒在該裝置上休眠的程序。無論是快速還是慢速處理例程,程式設計師都應該編寫執行事件盡可能短的處理例程。如果需要執行乙個長時間的計算任務,做好的辦法就是使用上下半部處理機制,以便讓工作在更安全的時間裡排程計算任務。

上半部的功能是響應中斷。當中斷發生時,它就把裝置驅動程式中中斷處理例程的下半部掛到裝置的下半部執行佇列中去,然後繼續等待新的中斷到來。這樣一來,上半部的執行速度就會很快,它就可以接受更多它負責的裝置所產生的中斷了。上半部之所以快,是因為它是完全遮蔽中斷的,如果它沒有執行完,其他中斷就不能及時地處理,只能等到這個中斷處理程式執行完畢以後。所以要盡可能多的對裝置產生的中斷進行服務和處理,中斷處理程式就一定要快。

下半部的功能是處理比較複雜的過程。下半部和上半部最大的區別是可中斷,而上半部卻不可中斷。下半部幾乎完成了中斷處理程式所有的事情,因為上半部只是將下半部排到了它們所負責的裝置中斷的處理佇列中去,然後就不做其它的處理了。下半部所負責的工作一般是檢視裝置以獲得產生中斷的事件資訊,並根據這些資訊(一般通過讀裝置上的暫存器得來)進行相應的處理。下半部是可中斷的,所以在執行期間,如果其它裝置產生了中斷,這個下半部可以暫時的中斷掉,等到那個裝置的上半部執行完了,再回頭執行這個下半部。

這上面大多數都是我們在查閱資料和聽老師講課獲取的知識內容但是具體是如何實現的呢?

也許我們也知道tasklet和work_queue。知道這兩個是完成下半部的。在具體的過程中我們將如何實現呢?

此處就是通過建立工作佇列的方式我們把初始化的操作都放在irq之前完成,在irq_handler()中將具體的工作提交到工作佇列中。使用的api為queue_work()。具體的細節問題希望讀者能夠查閱資料自行完成。

tasklet作為一種新機制,顯然可以承擔更多的優點。正好這時候smp越來越火了,因此又在tasklet中加入了smp機制,保證同種中斷只能在乙個cpu上執行。在軟中斷時代,顯然沒有這種考慮。因此同一種中斷可以在兩個cpu上同時執行,很可能造成衝突。

linux中斷下半部處理有三種方式:軟中斷、tasklet、工作佇列。

曾經有人問我為什麼要分這幾種,該怎麼用。當時用書上的東西蒙混了過去,但是自己明白自己實際上是不懂的。最近有時間了,於是試著整理一下linux的中斷處理機制,目的是起碼從原理上能夠說得通。

一、最簡單的中斷機制

最簡單的中斷機制就是像晶元手冊上講的那樣,在中斷向量表中填入跳轉到對應處理函式的指令,然後在處理函式中實現需要的功能。類似下圖:

這種方式在原來的微控制器課程中常常用到,一些簡單的微控制器系統也是這樣用。

它的好處很明顯,簡單,直接。

二、下半部

中斷處理函式所作的第一件事情是什麼?答案是遮蔽中斷(或者是什麼都不做,因為常常是如果不清除if位,就等於遮蔽中斷了),當然只遮蔽同一種中斷。之所以要遮蔽中斷,是因為新的中斷會再次呼叫中斷處理函式,導致原來中斷處理現場的破壞。即,破壞了 interrupt context。

隨著系統的不斷複雜,中斷處理函式要做的事情也越來越多,多到都來不及接收新的中斷了。於是發生了中斷丟失,這顯然不行,於是產生了新的機制:分離中斷接收與中斷處理過程。中斷接收在遮蔽中斷的情況下完成;中斷處理在時能中斷的情況下完成,這部分被稱為中斷下半部。

從上圖中看,只看int0的處理。func0為中斷接收函式。中斷只能簡單的觸發func0,而func0則能做更多的事情,它與funca之間可以使用佇列等快取機制。當又有中斷發生時,func0被觸發,然後傳送乙個中斷請求到快取佇列,然後讓funca去處理。

由於func0做的事情是很簡單的,所以不會影響int0的再次接收。而且在func0返回時就會使能int0,因此funca執行時間再長也不會影響int0的接收。

三、軟中斷

下面看看linux中斷處理。作為乙個作業系統顯然不能任由每個中斷都各自為政,統一管理是必須的。

我們不可中斷部分的共同部分放在函式do_irq中,需要新增中斷處理函式時,通過request_irq實現。下半部放在do_softirq中,也就是軟中斷,通過open_softirq新增對應的處理函式。

四、tasklet

舊事物跟不上歷史的發展時,總會有新事物出現。

隨著中斷數的不停增加,軟中斷不夠用了,於是下半部又做了進化。

軟中斷用輪詢的方式處理。假如正好是最後一種中斷,則必須迴圈完所有的中斷型別,才能最終執行對應的處理函式。顯然當年開發人員為了保證輪詢的效率,於是限制中斷個數為32個。

為了提高中斷處理數量,順道改進處理效率,於是產生了tasklet機制。

tasklet採用無差別的佇列機制,有中斷時才執行,免去了迴圈查表之苦。

總結下tasklet的優點:

(1)無型別數量限制;

(2)效率高,無需迴圈查表;

(3)支援smp機制;

五、工作佇列

前面的機制不論如何折騰,有一點是不會變的。它們都在中斷上下文中。什麼意思?說明它們不可掛起。而且由於是序列執行,因此只要有乙個處理時間較長,則會導致其他中斷響應的延遲。為了完成這些不可能完成的任務,於是出現了工作佇列。工作佇列說白了就是一組核心執行緒,作為中斷守護執行緒來使用。多個中斷可以放在乙個執行緒中,也可以每個中斷分配乙個執行緒。

工作佇列對執行緒作了封裝,使用起來更方便。

假如中斷數量很多,而且這些中斷都是自啟動型的(中斷處理函式會導致新的中斷產生),則有可能cpu一直在這裡執行中斷處理函式,會導致使用者程序永遠得不到排程時間。

為了避免這種情況,linux發現中斷數量過多時,會把多餘的中斷處理放到乙個單獨的執行緒中去做,就是ksoftirqd執行緒。這樣又保證了中斷不多時的響應速度,又保證了中斷過多時不會把使用者程序餓死。

六、使用方式總結

request_irq掛的中斷函式要盡量簡單,只做必須在遮蔽中斷情況下要做的事情。

中斷的其他部分都在下半部中完成。

軟中斷的使用原則很簡單,永遠不用。它甚至都不算是一種正是的中斷處理機制,而只是tasklet的實現基礎。

工作佇列也要少用,如果不是必須要用到執行緒才能用的某些機制,就不要使用工作佇列。其實對於中斷來說,只是對中斷進行簡單的處理,大部分工作是在驅動程式中完成的。所以有什麼必要非使用工作佇列呢?

除了上述情況,就要使用tasklet。

即使是下半部,也只是作必須在中斷中要做的事情,如儲存資料等,其他都交給驅動程式去做。

linux中斷處理原理分析

1 中斷概念 為什麼需要中斷?1 外設的處理速度一般慢於cpu 2 cpu不能一直等待外部事件 所以裝置必須有一種方法來通知cpu它的工作進度,這種方法就是中斷。2 中斷實現 在linux驅動程式中,為裝置實現乙個中斷包含兩個步驟 1 向核心註冊中斷 2 實現中斷處理函式 3 中斷註冊 reques...

linux中斷處理原理分析

部落格 fireaxe.blog.chinaunix.net tasklet作為一種新機制,顯然可以承擔更多的優點。正好這時候smp越來越火了,因此又在tasklet中加入了smp機制,保證同種中斷只能在乙個cpu上執行。在軟中斷時代,顯然沒有這種考慮。因此同一種中斷可以在兩個cpu上同時執行,很可...

linux中斷處理原理分析

tasklet作為一種新機制,顯然可以承擔更多的優點。正好這時候smp越來越火了,因此又在tasklet中加入了smp機制,保證同種中斷只能在乙個cpu上執行。在軟中斷時代,顯然沒有這種考慮。因此同一種中斷可以在兩個cpu上同時執行,很可能造成衝突。linux中斷下半部處理有三種方式 軟中斷 tas...