7.5Tasklets機制


7.5 Tasklet


關於時間,內核另外一個有力工具就是tasklet機制。它主要用於中斷管理。

Tasklet在某些方面與內核定時器類似。它們總是在中斷時運行,總是運行在調度它們的CPU上,且能夠接受unsigned long類型的參數。又不像內核定時器,不能要求在特定時間執行該功能。通過調度tasklet,你可以讓內核選擇在稍後的時間執行它。這種行爲對於中斷處理程序非常有用,硬件中斷必須儘可能快的處理,但是數據處理可以延遲後安全地進行。事實上,tasklet,就像內核定時器一樣,在“軟中斷”的上下文中被執行(原子模式),這是內核在使能硬件中斷的情況下執行異步任務的一種機制。

tasklet的數據結構如下所示,在使用之前必須被初始化。聲明可以使用下面的函數或宏。

#include <linux/interrupt.h>
struct tasklet_struct {
    /* ... */
    void (*func)(unsigned long);
    unsigned long data;
};

void tasklet_init(struct tasklet_struct *t, void (*func)(unsigned long), unsigned long data);
DECLARE_TASKLET(name, func, data);
DECLARE_TASKLET_DISABLED(name, func, data);

Tasklet提供了許多有趣的功能:

  • tasklet可以禁用和使能;
  • 就像計時器一樣,tasklet可以重新註冊自己;
  • tasklet可以以正常優先級或高優先級調度運行。後來的組總是先執行。
  • 如果系統負荷不是很重,tasklet可以立即執行,但是不遲於下一個定時器嘀嗒;
  • tasklet可以併發執行,但是同一個tasklet只能在一個處理器上運行且運行在調度它的CPU之上。

jit模塊包含2個文件,/proc/jitasklet/proc/jitasklethi,其返回與/proc/jitimer相同的數據。數據內容如下:

phon% cat /proc/jitasklet
 time delta inirq pid cpu command
 6076139 0 0 4370 0 cat
 6076140 1 1 4368 0 cc1
 6076141 1 1 4368 0 cc1
 6076141 0 1 2 0 ksoftirqd/0
 6076141 0 1 2 0 ksoftirqd/0
 6076141 0 1 2 0 ksoftirqd/0

第1行數據描述了調用進程的內容,其它行描述了運行tasklet程序的內容。

上面的數據證實,當CPU正在運行一個進程的時候,tasklet會在下一個定時器嘀嗒運行;否則,當CPU處於空閒時,它會立即運行。內核提供了一組ksoftirqd內核線程,每個CPU一個,只是爲了運行“軟中斷”處理程序,例如tasklet_action函數。因此,上面最後三個tasklet發生在ksoftirqd內核線程裏,其運行在CPU 0上。jitasklethi的實現,使用了高優先級的tasklet。下面的函數列表會有介紹。

jit模塊裏, /proc/jitasklet/proc/jitasklethi的實現與/proc/jitimer幾乎一樣。前兩個使用的是tasklet調用,後一個使用的timer相關調用。下面的列表就是tasklet相關接口:

  • void tasklet_disable(struct tasklet_struct *t);

    禁止給定的tasklet。仍可以使用tasklet_schedule調度tasklet,但是會延遲執行,直到再次使能tasklet爲止。如果tasklet當前正在運行,則此函數將等待,直到tasklet退出; 因此,在調用tasklet_disable之後,您可以確保tasklet沒有在系統中的任何位置運行。

  • void tasklet_disable_nosync(struct tasklet_struct *t);

    禁用tasklet,但不等待任何當前正在運行的函數退出。當它返回時,tasklet被禁用,並且在重新使能之前不會被調度,但是,它可以在另一個CPU上運行。

  • void tasklet_enable(struct tasklet_struct *t);

    啓用先前禁止的tasklet。與tasklet_disable函數成對使用。

  • void tasklet_schedule(struct tasklet_struct *t);

    調度tasklet執行。如果tasklet運行之前被調度,只運行一次;如果在運行中被調度,則運行完成後再執行一次。這可確保在處理其它事件時,剛發生的時間能夠得到應有的處理。這種行爲還允許tasklet重新調度自己。

  • void tasklet_hi_schedule(struct tasklet_struct *t);

    安排tasklet以更高的優先級執行。 當軟中斷處理程序運行時,它會在其它軟中斷任務(包括“普通”tasklet)之前處理高優先級的tasklet。 理想情況下,只有具有低延遲要求的任務(例如填充音頻緩衝區)才應使用此功能,以避免其它軟中斷處理程序引入的額外延遲。 實際上,/proc/jitasklethi/proc/jitasklet之間表現的差異我們是很難看出來的。

  • void tasklet_kill(struct tasklet_struct *t);

    “殺死”tasklet,保證不會再次運行;通常會在設備被關閉或模塊被移除時調用。如果已經運行,則該函數等待直到tasklet完成執行。在調用該函數之前不能再重新調度自己。

tasklet相關的實現位於kernel/softirq.c中。兩個tasklet列表(普通和高優先級)在每個CPU上都會聲明, 這點與內核定時器相同。在tasklet中使用的數據結構是一個單鏈表,因爲它沒有內核定時器所需要的排序要求。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章