軟中斷 tasklet 工作佇列

2021-06-26 05:29:13 字數 3302 閱讀 9645

軟中斷、tasklet和工作佇列並不是linux核心中一直存在的機制,而是由更早版本的核心中的「下半部」(bottom half)演變而來。下半部的機制實際上包括五種,但2.6版本的核心中,下半部和任務佇列的函式都消失了,只剩下了前三者。本文重點在於介紹這三者之間的關係。(函式細節將不會在本文中出現,可以參考文獻,點這裡)

(1)上半部和下半部的區別

上半部指的是中斷處理程式,下半部則指的是一些雖然與中斷有相關性但是可以延後執行的任務。舉個例子:在網路傳輸中,網絡卡接收到資料報這個事件不一定需要馬上被處理,適合用下半部去實現;但是使用者敲擊鍵盤這樣的事件就必須馬上被響應,應該用中斷實現。

兩者的主要區別在於:中斷不能被相同型別的中斷打斷,而下半部依然可以被中斷打斷;中斷對於時間非常敏感,而下半部基本上都是一些可以延遲的工作。由於二者的這種區別,所以對於乙個工作是放在上半部還是放在下半部去執行,可以參考下面四條:

a)如果乙個任務對時間非常敏感,將其放在中斷處理程式中執行。

b)如果乙個任務和硬體相關,將其放在中斷處理程式中執行。

c)如果乙個任務要保證不被其他中斷(特別是相同的中斷)打斷,將其放在中斷處理程式中執行。

d)其他所有任務,考慮放在下半部去執行。

(2)為什麼要使用軟中斷?

軟中斷作為下半部機制的代表,是隨著smp(share memory processor)的出現應運而生的,它也是tasklet實現的基礎(tasklet實際上只是在軟中斷的基礎上新增了一定的機制)。軟中斷一般是「可延遲函式」的總稱,有時候也包括了tasklet(請讀者在遇到的時候根據上下文推斷是否包含tasklet)。它的出現就是因為要滿足上面所提出的上半部和下半部的區別,使得對時間不敏感的任務延後執行,而且可以在多個cpu上並行執行,使得總的系統效率可以更高。它的特性包括:

a)產生後並不是馬上可以執行,必須要等待核心的排程才能執行。軟中斷不能被自己打斷,只能被硬體中斷打斷(上半部)。

b)可以併發執行在多個cpu上(即使同一型別的也可以)。所以軟中斷必須設計為可重入的函式(允許多個cpu同時操作),因此也需要使用自旋鎖來保護其資料結構。

(3)為什麼要使用tasklet?(tasklet和軟中斷的區別)

由於軟中斷必須使用可重入函式,這就導致設計上的複雜度變高,作為裝置驅動程式的開發者來說,增加了負擔。而如果某種應用並不需要在多個cpu上並行執行,那麼軟中斷其實是沒有必要的。因此誕生了彌補以上兩個要求的tasklet。它具有以下特性:

a)一種特定型別的tasklet只能執行在乙個cpu上,不能並行,只能序列執行。

b)多個不同型別的tasklet可以並行在多個cpu上。

c)軟中斷是靜態分配的,在核心編譯好之後,就不能改變。但tasklet就靈活許多,可以在執行時改變(比如新增模組時)。

tasklet是在兩種軟中斷型別的基礎上實現的,因此如果不需要軟中斷的並行特性,tasklet就是最好的選擇。

(4)為什麼要使用工作佇列work queue?(work queue和軟中斷的區別)

上面我們介紹的可延遲函式執行在中斷上下文中(軟中斷的乙個檢查點就是do_irq退出的時候),於是導致了一些問題:軟中斷不能睡眠、不能阻塞。由於中斷上下文出於核心態,沒有程序切換,所以如果軟中斷一旦睡眠或者阻塞,將無法退出這種狀態,導致核心會整個僵死。但可阻塞函式不能用在中斷上下文中實現,必須要執行在程序上下文中,例如訪問磁碟資料塊的函式。因此,可阻塞函式不能用軟中斷來實現。但是它們往往又具有可延遲的特性。

因此在2.6版的核心中出現了在核心態執行的工作佇列(替代了2.4核心中的任務佇列)。它也具有一些可延遲函式的特點(需要被啟用和延後執行),但是能夠能夠在不同的程序間切換,以完成不同的工作。

對於softirq,linux kernel中是在中斷處理程式執行的,具體的路徑為:

do_irq() --> irq_exit() --> invoke_softirq() --> do_softirq() --> __do_softirq()

在__do_softirq()中有這麼一段**:

do

h++;

pending >>= 1;

} while (pending);

複製**

你看,這裡就是對softirq進行處理了,因為pengding是乙個__u32的型別,所以每一位都對應了一種softirq,正好是32種(linux kernel中實際上只使用了前6種 ).

h->action(h),就是執行softirq的處理函式。

對於tasklet,前面已經說了,是一種特殊的softirq,具體就是第0和第5種softirq,所以說tasklet是基於softirq來實現的。

tasklet既然對應第0和第5種softirq,那麼就應該有對應的處理函式,以便h->action()會執行tasklet的處理函式。

我們看**:

softirq.c

void __init softirq_init(void)  

複製**

這裡註冊了兩種tasklet所在的softirq的處理函式,分別對應高優先順序的tasklet和低優先順序的tasklet。

我們看低優先順序的吧(高優先順序的也一樣)。

static void tasklet_action(struct softirq_action *a)

tasklet_unlock(t);

} local_irq_disable();

t->next = __get_cpu_var(tasklet_vec).list;

__get_cpu_var(tasklet_vec).list = t;

__raise_softirq_irqoff(tasklet_softirq);  

local_irq_enable();

} }

複製**

你看,在執行softirq的處理時(__do_softirq),對於

do

h++;

pending >>= 1;

} while (pending);

複製**

如果tasklet有任務需要處理,會執行到h->action(),這個函式指標就會指向tasklet_action(),然後在tasklet_action()裡再去執行tasklet對應的各個任務,這些任務都是掛在乙個全域性鍊錶裡面的,具體的**這裡就不分析了。

另外, softirq在smp中是可能被同時執行的,所以softirq的處理函式必須被編寫成可重入的函式。

但tasklet是不會在多個cpu之中同時執行的,所以tasklet的處理函式可以編寫成不可重入的函式,這樣就減輕了程式設計人員的負擔。

軟中斷 tasklet 工作佇列

深入理解linux核心 筆記4 軟中斷 tasklet 工作佇列 2009年06月02日 星期二 10 48 軟中斷 tasklet和工作佇列並不是linux核心中一直存在的機制,而是由更早版本的核心中的 下半部 bottom half 演變而來。下半部的機制實際上包括五種,但2.6版本的核心中,下...

軟中斷 tasklet 工作佇列

軟中斷 1 軟中斷作為下半部機制的代表,2 是隨著smp share memory processor 的出現應運而生的 3 軟中斷是tasklet實現的基礎 tasklet實際上只是在軟中斷的基礎上新增了一定的機制 4 軟中斷一般是 可延遲函式 的總稱 5 軟中斷可以在多個cpu上並行執行 6 軟...

軟中斷 tasklet和工作佇列

中斷機制的下半部實現機制 軟中斷 tasklet 工作佇列。軟中斷軟中斷適用於像網路這樣效能要求非常高的情況使用,可以再所有處理器上執行,兩個型別相同的軟中斷有可能被同時執行。軟中斷在編譯期間必須進行靜態註冊。軟中斷使用的比較少 軟中斷對時間要求比較嚴格,對加鎖要求高。如果需要擴充套件到多處理器執行...