四、中斷處理程序
Linux中的中斷處理程序很有特色,它的一個中斷處理程序分為兩個部分:上半部(tophalf)和下半部(bottom half)。之所以會有上半部和下半部之分,完全是考慮到中斷處理的效率。
上半部的功能是"登記中斷"。當一個中斷發生時,他就把裝置驅動程式中中斷例程的下半部掛到該裝置的下半部執行佇列中去,然後就沒事情了--等待新的中斷的到來。這樣一來,上半部執行的速度就會很快,他就可以接受更多她負責的設備所產生的中斷了。上半部之所以要快,是因為它是完全屏蔽中斷的,如果她不執行完,其它的中斷就不能被及時的處理,只能等到這個中斷處理程序執行完畢以後。所以,要盡量對設備產生的中斷進行服務和處理,中斷處理程序就一定要快。
但是,有些中斷事件的處理是比較複雜的,所以中斷處理程序必須多花一點時間才能夠把事情做完。但怎麼樣化解在短時間內完成複雜處理的矛盾呢,這時候Linux引進了下半部的概念。下半部和上半部最大的不同是下半部是可中斷的,而上半部是不可中斷的。
下半部幾乎做了中斷處理程序所有的事情,因為上半部只是將下半部排到了他們所負責的設備的中斷處理隊列中去,然後就什麼都不管了。下半部一般所負責的工作是察看設備以獲得產生中斷的事件信息,並根據這些信息(一般通過讀設備上的寄存器得來)進行相應的處理。如果有些時間下半部不知道怎麼做,他就用著名的鴕鳥演算法來解決問題--說白了就是忽略這個事件。
由於下半部是可中斷的,所以在它運行期間,如果其它的設備產生了中斷,這個下半部可以暫時的中斷掉,等到那個設備的上半部運行完了,再回頭來運行它。但有一點一定要注意,那就是如果一個設備中斷處理程序正在運行,無論她是運行上半部還是運行下半部,只要中斷處理程序還沒有處理完畢,在這期間設備產生的新的中斷都將被忽略掉。因為中斷處理程序是不可重入的,所以同一個中斷處理程序是不能並行的。
在Linux Kernel 2.0以前,中斷分為快中斷和慢中斷(偽中斷我們這裡不談),其中快中斷的下半部也是不可中斷的,這樣可以保證它執行的快一點。但是由於現在硬體水平不斷上升,快中斷和慢中斷的運行速度已經沒有什麼差別了,所以為了提高中斷例程事務處理的效率,從Linux kernel 2.0以後,中斷處理程序全部都是慢中斷的形式了--他們的下半部是可以中斷的。
但是,在下半部中,你也可以進行中斷屏蔽--如果某一段程式碼不能被中斷的話。你可以使用cti、sti或save_flag、restore_flag來實現你的想法。至於他們的用法和區別,請參考本文指定參考書中斷處理部分。
進一步的細節請讀者參看本文指定參考書,這裡就不再所說了,詳細介紹細節不是我的目的,我的目的是整理概念。
五、置中斷標誌位
在處理中斷的時候,中斷控制器會屏蔽掉原先發送中斷的那個設備,直到她發送的上一個中斷被處理完了為止。因此如果發送中斷的那個設備載中斷處理期間又發送了一個中斷,那麼這個中斷就被永遠的遺失了。
之所以發生這種事情,是因為中斷控制器並不能緩衝中斷信息,所以當前一個中斷沒有處理完以前又有新的中斷到達,他肯定會丟掉新的中斷的。但是這種缺陷可以透過設定主處理器(CPU)上的"置中斷標誌位元"(sti)來解決,因為主處理器具有緩衝中斷的功能。如果使用了"置中斷標誌位",那麼在處理完中斷以後使用sti函數就可以使先前被屏蔽的中斷得到服務。
以上就是深入淺出分析Linux裝置驅動程式中斷 (1)(2)的內容,更多相關內容請關注PHP中文網(www.php.cn)!