**:
注意:軟體中斷不是軟中斷。軟體中斷不依賴於底層架構,類似於訊號機制;而軟中斷依賴於底層架構,採用特殊的指令產生,系統呼叫就是採用的軟中斷,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核心裡,關於...