軟中斷和tasklet介紹


今天看了下tasklet,重點分析了其和軟中斷的關系,特此記錄


 

關於軟中斷,在之前的中斷文章中已經有所介紹,這里就不多說了,只是說明下,系統中默認支持32種軟中斷,而實際上系統定義的軟中斷僅有以下幾種。

enum
{
    HI_SOFTIRQ=0,
    TIMER_SOFTIRQ,
    NET_TX_SOFTIRQ,
    NET_RX_SOFTIRQ,
    BLOCK_SOFTIRQ,
    BLOCK_IOPOLL_SOFTIRQ,
    TASKLET_SOFTIRQ,
    SCHED_SOFTIRQ,
    HRTIMER_SOFTIRQ,
    RCU_SOFTIRQ,    /* Preferable RCU should always be the last softirq */

    NR_SOFTIRQS
};

 實際上並沒有什么關系,只有中樞的內核代碼才使用軟中斷,而如果用戶想要使用這種方式,直接使用軟中斷並不是一個好的選擇,內核為用戶提供了另外一種方便的方式即tasklet,tasklet本質上也是一種軟中斷,准確來說是系統從軟中斷類型中拿出一種來支持tasklet,所以tasklet就是一種軟中斷,不過在軟中斷的基礎上,tasklet進行了更細的划分。每個CPU維護一個tasklet鏈表,其中保存當前CPU所有注冊的tasklet。由於tasklet本質上仍然是軟中斷,所以其處理方式依賴於軟中斷的處理時機,在系統檢查處理軟中斷時,檢查到tasklet類型的軟中斷,調用tasklet_action函數進行處理。

static DEFINE_PER_CPU(struct tasklet_head, tasklet_vec);

 每個tasklet由一個tasklet_struct結構描述

struct tasklet_struct
{
    struct tasklet_struct *next;
    unsigned long state;
    atomic_t count;
    void (*func)(unsigned long);
    unsigned long data;
};

 

 所有的tasklet通過next連接成一個局部於CPU的鏈表,注意該結構中有個函數指針func,表示處理該tasklet的指針。所以要注冊tasklet還需要提供處理函數,軟中斷的處理函數已經由系統定義好的。通過tasklet_schedule函數可以注冊一個tasklet到系統

static inline void tasklet_schedule(struct tasklet_struct *t)
{
    if (!test_and_set_bit(TASKLET_STATE_SCHED, &t->state))
        __tasklet_schedule(t);
}

 

 

 

void __tasklet_schedule(struct tasklet_struct *t)
{
    unsigned long flags;

    local_irq_save(flags);
    t->next = NULL;
    *__this_cpu_read(tasklet_vec.tail) = t;
    __this_cpu_write(tasklet_vec.tail, &(t->next));
    raise_softirq_irqoff(TASKLET_SOFTIRQ);
    local_irq_restore(flags);
}

 

 實際的工作就比較簡單,實際上就是插入到CPU維護的tasklet鏈表的尾部。然后會調用raise_softirq_irqoff標記軟中斷位圖。這樣在下次處理軟中斷的時候,就會處理tasklet,進而處理注冊的tasklet。在操作CPU變量期間會禁用本地中斷。

 

明白了軟中斷和tasklet的關系,還需要注意:

1、軟中斷支持在不同CPU上並行運行,不管是同種類型的還是不同類型的。

2、tasklet僅僅支持不同類型的在不同CPU上並行運行,同種類型的不支持。

 

參考:

1、linux內核3.10.1源碼

2、深入linux內核架構

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM