linux裝置驅動 中斷下半部的三種實現機制

2021-10-09 17:36:31 字數 2465 閱讀 8357

軟中斷

軟中斷是一組靜態定義的下半部介面,有 32 個,可以在所有處理器上同時執行,型別相同,也可以在編譯時靜態註冊。

)**之中第一次就判斷是否在中斷處理中,如果在立刻退出函式。這說明了什麼?說明了如果有其他軟中斷觸發,執行到此處由於先前的軟中斷已經在處理,則其他軟中斷會返回。所以,軟中斷不能被另外乙個軟中斷搶占!唯一可以搶占軟中斷的是中斷處理程式,所以軟中斷允許響應中斷。雖然不能在本處理器上搶占,但是其他的軟中斷甚至同型別可以在其他處理器上同時執行。由於這點,所以對臨界區需要加鎖保護。

軟中斷留給對時間要求最嚴格的下半部使用。目前只有網路,核心定時器和 tasklet建立在軟中斷上。

tasklet

基於軟中斷實現的,靈活性強,動態建立的下半部實現機制。兩個不同型別的 tasklet 可以在不同處理器上執行,但相同的不可以,可以通過**動態註冊。

在 smp 上,呼叫 tasklet 是會檢測 tasklet_state_sched 標誌,如果同型別在執行,就退出函式。

tasklet 由於是基於軟中斷實現的,所以也允許響應中斷。但不能睡眠(我認為不能睡眠原因是它們內部有 spin lock)。

工作佇列

工作佇列(work queue)是另外一種將中斷的部分工作推後的一種方式,它可以實現一些tasklet不能實現的工作,比如工作佇列機制可以睡眠。這種差異的本質原因是,在工作佇列機制中,將推後的工作交給乙個稱之為工作者執行緒(worker thread)的核心執行緒去完成(單核下一般會交給預設的執行緒events/0)。因此,在該機制中,當核心在執行中斷的剩餘工作時就處在程序上下文(process context)中。也就是說由工作佇列所執行的中斷**會表現出程序的一些特性,最典型的就是可以重新排程甚至睡眠

對於tasklet機制(中斷處理程式也是如此),核心在執行時處於中斷上下文(interrupt context)中。而中斷上下文與程序毫無瓜葛,所以在中斷上下文中就不能睡眠。因此,選擇tasklet還是工作佇列來完成下半部分應該不難選擇。當推後的那部分中斷程式需要睡眠時,工作佇列毫無疑問是你的最佳選擇;否則,還是用tasklet吧。

在了解中斷上下文時,先來回顧另乙個熟悉概念:程序上下文(這個中文翻譯真的不是很好理解,用「環境」比它好很多)。一般的程序執行在使用者態,如果這個程序進行了系統呼叫,那麼此時使用者空間中的程式就進入了核心空間,並且稱核心代表該程序執行於核心空間中。由於使用者空間和核心空間具有不同的位址對映,並且使用者空間的程序要傳遞很多變數、引數給核心,核心也要儲存使用者程序的一些暫存器、變數等,以便系統呼叫結束後回到使用者空間繼續執行。這樣就產生了程序上下文。

所謂的程序上下文,就是乙個程序在執行的時候,cpu的所有暫存器中的值、程序的狀態以及堆疊中的內容。當核心需要切換到另乙個程序時(上下文切換),它需要儲存當前程序的所有狀態,即儲存當前程序的程序上下文,以便再次執行該程序時,能夠恢復切換時的狀態繼續執行。上述所說的工作佇列所要做的工作都交給工作者執行緒來處理,因此它可以表現出程序的一些特性,比如說可以睡眠等。

對於中斷而言,是硬體通過觸發訊號,導致核心呼叫中斷處理程式,進入核心空間。這個過程中,硬體的一些變數和引數也要傳遞給核心,核心通過這些引數進行中斷處理,中斷上下文就可以理解為硬體傳遞過來的這些引數和核心需要儲存的一些環境,主要是被中斷的程序的環境。因此處於中斷上下文的tasklet不會有睡眠這樣的特性。

訊號量會導致睡眠

中斷發生以後,cpu跳到核心設定好的中斷處理**中去,由這部分核心**來處理中斷。這個處理過程中的上下文就是中斷上下文。

為什麼可能導致睡眠的函式都不能在中斷上下文中使用呢? 首先睡眠的含義是將程序置於「睡眠」狀態,在這個狀態的程序不能被排程執行。然後,在一定的時機,這個程序可能會被重新置為「執行」狀態,從而可能被排程執行。 可見,「睡眠」與「執行」是針對程序而言的,代表程序的task_struct結構記錄著程序的狀態。核心中的「排程器」通過task_struct對程序進行排程。

但是,中斷上下文卻不是乙個程序,它並不存在task_struct,所以它是不可排程的。所以,在中斷上下文就不能睡眠。

那麼,中斷上下文為什麼不存在對應的task_struct結構呢?

中斷的產生是很頻繁的(至少每毫秒(看配置,可能10毫秒或其他值)會產生乙個時鐘中斷),並且中斷處理過程會很快。如果為中斷上下文維護乙個對應的task_struct結構,那麼這個結構頻繁地分配、**、並且影響排程器的管理,這樣會對整個系統的吞吐量有所影響。

但是在某些追求實時性的嵌入式linux中,中斷也可能被賦予task_struct結構。這是為了避免大量中斷不斷的巢狀,導致一段時間內cpu總是執行在中斷上下文,使得某些優先順序非常高的程序得不到執行。這種做法能夠提高系統的實時性,但是代價中吞吐量的降低

linux中斷與下半部

中斷 解決cpu和硬體速度差距太大問題,不能讓cpu等,也不能讓cpu輪詢,所以硬體好了給cpu發個訊號 硬體 控制器 中斷控制器 cpu 中斷控制器在中斷線啟用 未被遮蔽 才發向cpu 中斷 不需要與cpu時鐘同步,非同步,隨時可以來 異常 缺頁,0除 與cpu時鐘同步,同步,cpu產生,如系統呼...

筆記 中斷,下半部

先弄清兩個概念,程序上下文和中斷上下文 處理器總處於以下狀態中的一種 核心態,執行於程序上下文,核心代表程序執行於核心空間 核心態,執行於中斷上下文,核心代表硬體執行於核心空間 使用者態,執行於使用者空間。使用者空間的應用程式,通過系統呼叫,進入核心空間。這個時候使用者空間的程序要傳遞很多變數 引數...

linux中斷的上半部和下半部

本文 與linux中斷息息相關的乙個重要概念是linux中斷分為兩個半部 上半部 tophalf 和下半部 bottom half 上半部的功能是 登記中斷 當乙個中斷發生時,它進行相應地硬體讀寫後就把中斷例程的下半部掛到該裝置的下半部執行佇列中去。因此,上半部執行的速度就會很快,可以服務更多的中斷...