Linux中断下半部tasklet
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 <linux/module.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/jiffies.h>
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");