1. 程式人生 > 實用技巧 >中斷和中斷處理

中斷和中斷處理


author: lunar
date: Wed 21 Oct 2020 04:41:06 PM CST

中斷和中斷處理

任何作業系統的核心任務,都包含了對於連線到計算機上的硬體裝置進行管理。所謂管理,即與這些裝置進行通訊。然而,CPU的處理速度與這些硬體的速度不在一個數量級上。這就導致CPU在進行一次通訊後,往往要等待多個時鐘週期後才會接到下一次通訊。

如果讓CPU對這些裝置進行輪詢,將會嚴重拉低CPU的執行效率,因為大部分輪詢都是做的無用功。

更好的辦法是提供一種機制,讓硬體裝置在需要的時候向核心發出訊號表示有資料需要處理。這就是中斷機制。

中斷

中斷並不是軟體層面的實現,而是在硬體層面都得到了支援。例如,在敲擊鍵盤時,控制鍵盤的硬體裝置就會發生一箇中斷,中斷本質上是一種特殊的電訊號,由硬體裝置傳送給處理器。處理器接收到中斷訊號後,就會馬上報告給作業系統,然後由作業系統處理這些資料。

因此,作業系統隨時可能因為到來的中斷而被打斷。

不同的裝置對應的中斷不同,而每個中斷都有一個唯一的數字標誌,這樣作業系統才能區分不同硬體裝置的中斷。

中斷處理程式

在響應一個特定中斷的時候,核心會執行一個函式,稱為中斷處理程式。中斷處理程式工作在中斷上下文中。中斷隨時可能發生,因此中斷處理程式隨時可能執行。

上半部與下半部的對比

我們一般將中斷處理分為兩個部分,中斷處理程式是上半部——接收到一箇中斷就立刻執行,但是隻完成一些有嚴格時限的工作,例如對中斷進行應答等。

以網絡卡為例。當網絡卡接收到來自網路的資料包時,需要通知核心資料包到了。因此,網絡卡發出中斷,核心通過中斷處理程式進行應答。

中斷開始執行,通知硬體將網絡卡的資料拷貝到記憶體中。這些都是非常緊急的工作,如果不能及時執行,很容易造成網絡卡的快取溢位。但是拷貝到記憶體之後並不代表已經完成,可能使用者希望資料下載到磁碟,所以還要從記憶體寫入到磁碟。但是這個並不是很緊急的事情,所以放到中斷的下半部完成。

註冊中斷處理程式

驅動程式可以通過 request_irq() 函式註冊一箇中斷處理程式:

int request_irq(unsigned int irq, irq_handler_t handler, unsigned long flags, const char* name, void* dev);

irq表示要分配的中斷號,handler是一個指向處理這個中斷處理程式的指標。

中斷處理程式標誌

在繫結中斷處理程式時可以繫結以下標誌:

  • IRQF_DISABLED

    該標誌被設定後,核心在處理中斷處理程式本身期間,要禁止其它所有的中斷;

  • IRQF_SAMPLE_RANDOM

    表明這個裝置產生的中斷會對核心熵池(entropy pool)有貢獻,核心熵池負責提供由各種隨機事件匯出的真正的隨機數。

  • IRQF_TIMER

    特別為系統定時器的中斷處理而準備的

  • IRQF_SHARED

    表明可以在多箇中斷處理程式之間共享中斷線。在同一個給的你個線上註冊的每個處理程式必須制定這個標誌。

釋放中斷處理程式

解除安裝中斷處理程式時,需要登出相應的中斷處理程式,並釋放中斷線。需呼叫:

void free_irq(unsigned int irq, void* dev);

如果相應的中斷線是共享的,那麼僅僅登出中斷處理程式。否則相應中斷線也會被禁用。

中斷上下文

中斷上下文與程序上下文並不相同。程序上下文是核心的一種操作模式,此時核心代替程序執行,可以通過current巨集關聯到當前程序。程序上下文可以睡眠,也可以呼叫排程程式。

而中斷上下文,沒有後備程序,也不能進行睡眠,否則沒法進行重新排程。所以在中斷處理程式中不能出現睡眠函式。

中斷處理程式棧的設定是一個配置選項。早期,中斷處理程式並不具有自己的棧,它們必須共享所中斷程序的核心棧。

中斷處理機制的實現

圖中的硬體裝置發生一箇中斷,通過匯流排將電訊號傳送給中斷控制器,如果中斷線已被啟用,這個工作實際上就是通過電訊號給處理器的一個針腳傳送一個訊號。而處理器會立即停止正在做的事,跳到記憶體中預定義的位置開始執行程式碼,這個位置就是中斷處理程式的入口點。