Linux中斷和中斷處理

2021-08-28 01:45:58 字數 4102 閱讀 5850

眾所周知,處理器的速度跟外圍的硬體裝置的速度往往不在乙個數量級上,因此,如果核心採取讓處理器傳送乙個請求,然後專門等待回應的辦法,顯然差強人意。既然硬體處理的這麼慢,那麼核心就應該在這期間去處理其他事務,等待硬體真正完成了請求的操作後,再回過頭來對它進行處理。

輪詢(polling)可能會是一種解決辦法。它可以讓核心定期對裝置的狀態進行查詢,然後做出相應的處理。不過這種方法可能會讓核心做不少不用功。更好的辦法是提供一種機制,讓硬體在需要的時候想核心發出訊號,這就是中斷機制。

中斷使得硬體得以發出通知給處理器。在你敲擊鍵盤的時候,鍵盤控制器會傳送乙個中斷,通知作業系統有鍵按下。中斷本質上是一種特殊的電訊號,有硬體裝置向處理器發出。處理器收到中斷後,會馬上向作業系統反應此訊號的到來,然後就由作業系統負責處理這些新到來的資料。硬體裝置生成中斷的時候並不考慮處理器的時鐘同步---換句話說就是中斷隨時產生,因此,核心隨時可能因為新到來的中斷而被打斷。

在相應乙個特定中斷的時候,核心會執行乙個函式,該函式叫作中斷處理程式或中斷服務例程(interrupt service routine,isr)。產生中斷的每個裝置都有乙個相應的中斷處理程式。例如:由乙個函式專門處理來自系統時鐘的中斷,而另外乙個函式專門處理鍵盤產生的中斷。乙個裝置的中斷程式時它裝置驅動程式的一部分---裝置驅動程式是用於對裝置進行管理的核心**。中斷處理程式負責通知硬體裝置中斷已經被接收。同時中斷程式還要處理其他工作,比如要把來自硬體的網路資料報拷貝到記憶體,對其進行處理後再交給合適的協議棧或應用程式。

又想中斷處理程式執行的快,又想中斷程式完成的工作多,這兩個目的顯然有所牴觸。鑑於兩個目的之間存在的此消彼長的矛盾關係,所以我們一般把處理切為兩半部分執行。中斷時上半部分(top half)---接收到乙個中斷,它就立即執行,但是做有嚴格時限的工作,例如對接收的中斷進行應答或者復位硬體,這些工作都是所有中斷被禁止的情況下完成的。能夠被允許稍後完成的工作會推遲到下半部(bottom half)去。此後,在合適的時機,下半部會被中斷執行。

當執行乙個中斷處理程式時,核心處於中斷上下文(interrput context)中。程序上下文是一種核心所處的操作模式,此時核心代表程序執行---例如,執行系統呼叫或執行核心執行緒。在程序上下文中,可以通過current巨集關聯當前程序。此外,因為程序是以程序上下文的形勢連線到核心中的,因此,程序上下文可以睡眠,也可以呼叫排程程式。

與之相反,中斷上下文和程序並沒有什麼瓜葛。與current巨集也是不相干的。因為沒有後備程序,所以中斷上下文不可以休眠,否則又怎能再對它重新排程呢?,因此,不能從中斷上下文中呼叫某些函式。如果乙個函式睡眠,就不能在你的中斷處理程式中使用它---這是對什麼樣的函式可以在中斷成立程式中使用的限制。

中斷上下文具有較為嚴格的時間限制。因為它打斷了其他**。中斷上下文的**應當迅速,簡潔,盡量不要使用迴圈去處理繁重的工作。盡量把工作從中斷處理程式中分離出來,放在下半部來執行,因為下半部可以在更合適的時間執行。

中斷處理程式之前並不具有自己的棧,他們共享所有程序的核心棧,核心棧的大小是兩頁,在32位的體系結構上是8kb,在64位體系結構上是16kb。因為在這種設定中,中斷處理共享別人的堆疊。2.6早期版本的核心中,增加了乙個選項,把棧的大小從兩頁減小到一頁。也就是32位系統只提供4kb的棧。這就減輕了記憶體的壓力,因為系統中每個程序原先都需要兩頁連續,且不可換出的核心記憶體。為了應對棧大小的壓力,中斷處理程式擁有了自己的棧。

中斷處理系統在linux中的實現是非常依賴體系結構的,實現依賴於處理器、所使用的中斷控制器的型別、體系結構的設計以及機器本身。

下圖是中斷從硬體到核心的路由,裝置產生中斷,通過匯流排把電訊號傳送給中斷控制器,如果中斷線是啟用的(他們是允許被遮蔽的),那麼中斷控制器就會把中斷發往處理器。在大多數體系結構中,這個工作就是通過電訊號給處理器的特定管腳傳送乙個訊號。除非在處理器上禁止該中斷,否則,處理器會立即停止它正在做的事情,關閉中斷系統,然後調到記憶體中預定義的位置開始執行那裡的**。這個預定義的位置是由核心設定的,是中斷處理程式的入口點。

linux核心提供了一組介面用於操作機器上的中斷狀態。這些介面為我們提供了能夠禁止當預處理器的中斷系統,或遮蔽掉整個機器的一條中斷線的能力,這些例子都是與體系結構相關的。

控制中斷系統的原因歸根結底是需要提供同步。通過禁止中斷,可以確保某個中斷處理程式不會搶占當前的**。此外,禁止中斷還可以禁止核心搶占。然而,不管是禁止中斷還是禁止核心搶占,都沒有提供任何的保護機制來防止來自其他處理器的併發訪問。linux支援多處理器,因此,核心**一般需要獲取某種鎖,防止來自其他處理器對共享資料的併發訪問。獲取這些鎖的同時也伴隨著禁止本地中斷。鎖提供保護機制,防止來自其他處理器的併發訪問,而禁止中斷提供提供保護機制,則是防止來自其他中斷程式併發訪問。

中斷處理程式時核心中很有用的部分,但是由於本身存在的一些侷限,所以它只能完成整個中斷處理流程的上半部分,這些侷限包括:

現在,為什麼中斷處理程式只能作為整個硬體處理流程一部分的原因就很明顯了,作業系統必須有乙個快速、非同步、簡單的機制對硬體作出迅速響應並完成那些時間要求嚴格的操作。中斷處理程式很適合於實現這些功能,可是對於那些其他的、對時間要求相對寬鬆的任務,就應該推後到中斷被啟用以後再去執行。

這樣,整個中斷處理流程就被分為兩個部分,或叫兩半。第一部分是中斷處理程式(上半部),核心通過對它的非同步執行完成對硬體中斷的即時相應。

下半部的任務就是執行與中斷處理密切相關但中斷處理程式本身不執行的工作。在理想情況下,最好是中斷處理程式將所有工作都交給下半部執行,因為我們希望給在中斷處理程式中完成的工作越少越好,我們期望中斷處理程式能夠盡快地返回。

但是,中斷處理程式注定要完成一部分工作。例如:中斷處理程式機會都需要通過操作硬體對中斷的到達進行確認,有時它還會從硬體拷貝資料。因為這些工作對時間非常敏感,所以只能靠中斷處理程式自己去完成。

剩下的幾乎所有其他工作都是下半部執行的目標。例如:如果你在上半部中把資料從硬體拷貝到了內容,那麼當然應該在下半部中處理他們。遺憾的是,並不存在嚴格明確的規定來說明到底什麼任務應該在哪個部分中完成--如何做決定完全取決於驅動程式開發者自己的判斷。儘管在理論上不存在什麼錯誤,但輕率的實現效果往往不很理想。中斷處理程式會非同步執行,並且在最好的情況下它也會鎖定當前的中斷執行緒。因此將中斷處理程式持續執行的時間縮短到最小程度顯然非常重要。對於上半部和下半部之間劃分工作,儘管不存在某種嚴格的規則,但還是有一些提示可以借鑑:

和上半部只能通過中斷程式實現不同,下半部可以通過多種機制實現:工作佇列、軟中斷、tasklet。

軟中斷是執行中斷指令產生的,而硬中斷是由外設引發的。軟中斷使用的比較少,而tasklet是下半部更常用的一種形式,tasklet是通過軟中斷實現的。軟中斷是在編譯期間靜態分配的,他不能向tasklet那樣能被動態的註冊或登出。

目前只有兩個子系統直接使用軟中斷網路和scsi.

tasklet是利用軟中斷實現的一種下半部機制。選擇到底用軟中斷還是tasklet其實很簡單:通常應該用tasklet,它與軟中斷本質上很相似,行為表現也相近,但是介面更簡單,鎖保護也要求低。

工作佇列(work queue)是另外一種將工作退後執行的形式,它和我們前面討論的形式不同。工作佇列把工作推後,交給乙個核心執行緒去執行---這個下半部分總是會在程序上下文中執行。這樣,通過工作佇列執行的**能佔盡程序上下文的所有優勢。最重要的是工作佇列允許重新排程和睡眠。

通常在工作佇列和軟中斷/tasklet中做出選擇很容易,如果要推後執行的任務需要睡眠,那麼就選擇工作佇列。如果推後執行的任務不需要睡眠,那麼就選擇軟中斷或tasklet。

如果需要用乙個可以重新排程的實體來執行下半部處理,應該選擇使用工作佇列,他是唯一能在程序上下文中執行的下半部機制,也只有它可以睡眠,這意味著需要獲得大量記憶體是、需要獲取訊號量時、需要執行阻塞i/o操作時,它會非常有用。

各種不同的下半部實現機制之間做出選擇是很重要的。一般的驅動程式開發者需要做出兩個選擇,首先是你虛部乙個可排程的實體來執行推後的工作或者說需要休眠嗎?要是有,工作佇列就是唯一選擇,否則就是用tasklet。如果專注效能提高就考慮軟中斷。

Linux學習 中斷和中斷處理

2 中斷處理程式 3 上半部和下半部的對比 處理器的速度和外圍裝置的速度相差太遠,為了解決讓核心不做過多的無用功 使用輪詢 這是就需要一種機制在硬體需要時再向核心發出訊號 中斷機制 中斷機制可以更好的協同處理器和外部裝置,並且提高機器的效能 中斷 指的是可以使得硬體得以發出通知給處理器,中斷可以隨時...

Linux核心實現中斷和中斷處理(一)

核心是怎麼知道應用程式要呼叫系統呼叫的呢?或者說應用程式怎麼通知系統核心自己需要執行乙個系統呼叫,這是通過軟中斷實現的,通過引發乙個異常來促使系統切換到核心態去執行異常處理程式 ps 什麼時候會從使用者態切換到核心態呢?1.中斷 2.陷阱 3.系統呼叫 中斷分為兩種,硬中斷和軟中斷 在許多處理器體系...

Linux中斷處理

裝置管理過程中,中斷號的申請是乙個非常重要的操作。當裝置發出中斷之後,硬體裝置根據intel cpu的通用處理過程,跳轉到了該中斷號對應的中斷相應函式處。在linux作業系統中,必定要跳到do irq函式處。在do irq 函式中,進行了一部分公共的中斷響應處理之後,根據已經入棧了的中斷號查詢裝置中...