2019年2月6日 星期三

Linux中斷下半部tasklet

Source https://codertw.com/%E7%A8%8B%E5%BC%8F%E8%AA%9E%E8%A8%80/609807/


tasklet是Linux核心中“可延遲執行”機制、或“中斷下半部”的一種。tasklet的優先順序別較低,而且中斷處理過程中可以被打斷。但被打斷之後,還能進行自我恢復,斷點續執行。

1.資料結構

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

2.初始化

/* 靜態 */
//可以直接用tasklet_schedule()排程
#define DECLARE_TASKLET(name, func, data) \
struct tasklet_struct name = { NULL, 0, ATOMIC_INIT(0), func, data }
//需要使用tasklet_enable()使能,才可以被排程執行
#define DECLARE_TASKLET_DISABLED(name, func, data) \
struct tasklet_struct name = { NULL, 0, ATOMIC_INIT(1), func, data }
/* 動態 */
extern void tasklet_init(struct tasklet_struct *t,void (*func)(unsigned long), unsigned long data);

3.排程tasklet

//將tasklet加入到排程連結串列裡面,tasklet就能得到執行,每呼叫這個函式一次,tasklet只能執行一次,要再次執行需要重新呼叫這個函式
static inline void tasklet_schedule(struct tasklet_struct *t);

4.銷燬tasklet

//裝置關閉和模組解除安裝的時候,呼叫來殺死tasklet。如果當前tasklet在執行,會等待完成後,再殺死
extern void tasklet_kill(struct tasklet_struct *t);
extern void tasklet_kill_immediate(struct tasklet_struct *t, unsigned int cpu);

5.其他tasklet介面

static inline int tasklet_trylock(struct tasklet_struct *t)
static inline void tasklet_unlock(struct tasklet_struct *t)
static inline void tasklet_unlock_wait(struct tasklet_struct *t)
//比tasklet_schedule優先順序更高,可以得到更快處理
static inline void tasklet_hi_schedule(struct tasklet_struct *t)
//和tasklet_hi_schedule差不多,只是更安全
static inline void tasklet_hi_schedule_first(struct tasklet_struct *t)
//和tasklet_disable一樣,如果當前tasklet在執行,這個函式不會等待完成就先返回,當tasklet完成退出後,再禁止。 
static inline void tasklet_disable_nosync(struct tasklet_struct *t)
//禁止tasklet,即使tasklet_schedule已經把tasklet新增到排程連結串列裡,也得不到執行,必須要用tasklet_enable使能才可以。如果當前tasklet正在執行,tasklet_disable會等待執行完,然後禁止,返回。 
static inline void tasklet_disable(struct tasklet_struct *t)
//使能tasklet,和tasklet_disable要成對使用    
static inline void tasklet_enable(struct tasklet_struct *t)
//和tasklet_enable一樣
static inline void tasklet_hi_enable(struct tasklet_struct *t)
================================================================================================
struct tasklet_hrtimer {
struct hrtimer      timer;
struct tasklet_struct   tasklet;
enum hrtimer_restart    (*function)(struct hrtimer *);
};
extern void
tasklet_hrtimer_init(struct tasklet_hrtimer *ttimer,enum hrtimer_restart (*function)(struct hrtimer *),clockid_t which_clock, enum hrtimer_mode mode);
static inline 
int tasklet_hrtimer_start(struct tasklet_hrtimer *ttimer, ktime_t time,const enum hrtimer_mode mode)
static inline void tasklet_hrtimer_cancel(struct tasklet_hrtimer *ttimer)

6.驅動例項

#include 
#include 
#include 
#include 
static struct tasklet_struct test_tasklet;
static void function(unsigned long data)
{
printk(KERN_INFO "=======before schedule:%ld, in running:%ld=======\n",data,jiffies);
}
static int __init tasklet_test_init(void)
{
unsigned long tmp;
tmp = jiffies;
tasklet_init(&test_tasklet, function, tmp);
tasklet_schedule(&test_tasklet);
printk(KERN_ALERT "==============tasklet_test_init===============\n");
return 0;
}
static void __exit tasklet_test_exit(void)
{
printk(KERN_ALERT "==============tasklet_test_exit===============\n");
tasklet_kill(&test_tasklet);
}
module_init(tasklet_test_init);
module_exit(tasklet_test_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR( "wyy");

沒有留言: