1. 程式人生 > >軟中斷和tasklet介紹

軟中斷和tasklet介紹

表示 種類 blog 連接 關系 定義 深入 tor 好的

今天看了下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內核架構

軟中斷和tasklet介紹