linux軟體中斷 tasklet機制

2021-06-22 11:41:11 字數 3648 閱讀 1610

**:

注意:軟體中斷不是軟中斷。軟體中斷不依賴於底層架構,類似於訊號機制;而軟中斷依賴於底層架構,採用特殊的指令產生,系統呼叫就是採用的軟中斷,arm架構下使用swi指令產生軟中斷。

本文只是對tasklet作乙個粗淺的解釋,不對之處敬請指正!

本節我們先來說一下為什麼要引入軟體中斷?

一般來說,一次中斷服務的過程通常可以分為兩個部分。開頭的 部分往往必須在關中斷的條件下執行,這樣才能在不受干擾的條件下「原子」地完成一些關鍵性操作,同時這部分操作的時間性又往往很強,必須在中斷請求發生後立即或至少在一定時間限制中執行,而且相繼的多次中斷請求也不能合併在一起來處理。而後半部分,通常可以而且應該在開中斷的條件下執行,這樣才不至於因中斷關閉過久而造成其他中斷的丟失,同時,這些操作常常允許延時到稍後才來執行,而且有可能多次中斷的相關部分合併在一起處理。這些不同的性質常常使中斷服務的前後兩半明顯地區分開來,可以而且應該分別加以不同的實現。這裡的後半部分就稱為"bottom half",在核心**中往往寫成bf ,而bf的這部分就可以通過軟體中斷來實現。因為軟體中斷的啟用是通過**來實現的,而不是硬體,所以就可以自己或由系統來決定啟用的時機!

那麼軟體中斷具體在什麼時候啟用呢?

我們一般認為有兩個時機:

第乙個時機:do_irq完成後,在退出的時候呼叫irq_exit

do_irq

irq_exit();

if (!in_interrupt() && local_softirq_pending())//如果不處在中斷上下文並且軟體中斷開啟的話,就啟用軟體中斷

invoke_softirq();

do_softirq();

__do_softirq();

h = softirq_vec;

h->action(h);

第乙個時機一般可以處理大部分的軟體中斷,但是如果軟體中斷過多的話,不能在這個時機完成,那麼別擔心,還有第二個時機!

第二處:如果在irq_exit中沒有完成軟體中斷的話,會呼叫後台守護程序ksoftirqd

我們得先看一看守護程序的建立:

early_initcall(spawn_ksoftirqd);

spawn_ksoftirqd

cpu_callback(&cpu_nfb, cpu_online, cpu);

p = kthread_create_on_node(run_ksoftirqd, hcpu,cpu_to_node(hotcpu), "ksoftirqd/%d", hotcpu);

這裡建立了核心執行緒 run_ksoftirqd

我們看看呼叫核心執行緒,我們看看如何啟用呢?

raise_softirq

raise_softirq_irqoff(nr);

wakeup_softirqd();

struct task_struct *tsk = __this_cpu_read(ksoftirqd);

wake_up_process(tsk);

我們看看這個執行緒做了什麼:

run_ksoftirqd

__do_softirq();

h->action(h);//果然

當然還有網絡卡驅動用到的軟體中斷,我們先不說!

以上所謂的排程時機,實際上並不是軟中斷必須的,而是核心中基於軟中斷的tasklet機制所實現的!軟中斷說白了就是先寫乙個函式,然後在我們想執行這個函式的時候去啟用它,我們完全可以自己來規劃其啟用時機!但是事實上,軟體的開發人員並不建議我們自己註冊新的軟體中斷,核心為我們搭建了乙個使用軟體中斷的框架,這就是tasklet機制,而tasklet機制正是為了實現中斷的下半部!

那麼要使用這個機制我們需要做些什麼呢?

1、建立

declare_tasklet(name, func, data)

我們可以看看其定義:

#define declare_tasklet(name, func, data) 

struct tasklet_struct name =

由此我們也可以看出,我們也能直接這樣定義:

struct tasklet_struct name =

同時我們還得構造

func,這就是然間中斷的執行函式!

2、初始化:

void tasklet_init(struct tasklet_struct *t,void (*func)(unsigned long), unsigned long data)

只是完成了賦值的工作!

3、排程

static inline void tasklet_schedule(struct tasklet_struct *t)

tasklet_schedule

__tasklet_schedule(t);

raise_softirq_irqoff(tasklet_softirq);

__raise_softirq_irqoff(nr);//開啟軟中斷

or_softirq_pending(1ul << nr);

if (!in_interrupt())

wakeup_softirqd();

struct task_struct *tsk = __this_cpu_read(ksoftirqd);

if (tsk && tsk->state != task_running)

wake_up_process(tsk);//開啟守護程序,就執行了軟體中斷處理函式!

tasklet_schedule這個函式裡面我們有可能去執行軟體中斷,但是並不一定,如果處於中斷上下文,或者已經執行,就會立即返回,所以這個函式做的最有意義的一件事情就是

__raise_softirq_irqoff(nr),開啟了中斷!

就先跟我們上面分析的一樣,排程的時機有以上兩種。

但是現在還是有點糊塗,tasklet軟體中斷到底是如何掛鉤的呢,我們就要從軟體中斷的初始化來說起了:

softirq_init();

open_softirq(tasklet_softirq, tasklet_action);

open_softirq(hi_softirq, tasklet_hi_action);//這裡註冊了兩個軟中斷

當do_softirq啟用軟中斷的時候,實際上是呼叫

tasklet_action這個函式,在由

tasklet_action來呼叫我們在tasklet機制實現的處理函式,我們進入tasklet_action函式,看到它會遍歷鍊錶,來執行func函式!

軟體中斷呼叫

dos功能呼叫 dos中斷號範圍 0x20h 0x3fh,總共32個中斷向量 int 21h 01h號子功能 等待從鍵盤輸入乙個字元,同時將該字元顯示在顯示器上 入口引數 無 出口引數 al 按鍵的ascii碼 02h號子功能 顯示乙個字元 入口引數 dl 待顯示字元的ascii碼 出口引數 無 0...

Linux中斷和中斷處理

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

linux中斷巢狀以及中斷丟失

在linux核心裡,如果驅動在申請註冊中斷的時候沒有特別的指定,do irq在做中斷響應的時候,是開啟中斷的,如果在驅動的中斷處理函式正在執行的過程中,出現同一裝置的中斷或者不同裝置的中斷,這時候新的中斷會被立即處理,還是被pending,等當前中斷處理完成後,再做處理。在2.4和2.6核心裡,關於...