中断下半部:由于中断处理力求时间短,所以引出了下半部。
tasklet工作在中断上下文,处理中不允许休眠,而workqueue工作在进程上下文,这是不同点。
1,softirq: 处理比较快,但是内核级别的机制,需要修改整个内核源码,不推荐也不常用
2,tasklet: 内部实现实际调用了softirq
3, workqueue: 工作队列
1,tasklet:
struct tasklet_struct
{
struct tasklet_struct *next;
unsigned long state;
atomic_t count;
void (*func)(unsigned long); // 下半部的实现逻辑
unsigned long data; // 传递给func
};
a, 初始化
struct tasklet_struct mytasklet;
tasklet_init(struct tasklet_struct * t, void(* func)(unsigned long), unsigned long data)
例子:
void key_tasklet_half_irq(unsigned long data)
{
// 表示有数据,需要去唤醒整个进程/等待队列
wake_up_interruptible(&key_dev->wq_head);
//同时设置标志位
key_dev->key_state = 1;
//发送信号
kill_fasync(&key_dev->faysnc, SIGIO, POLLIN);
}
tasklet_init(&key_dev->mytasklet, key_tasklet_half_irq, 45);
b,在上半部中放入到内核线程中--启动
// 启动下半步
tasklet_schedule(&key_dev->mytasklet);
c,模块卸载的时候:
tasklet_kill(&key_dev->mytasklet);
2,工作队列和工作
typedef void (*work_func_t)(struct work_struct *work);
struct work_struct {
atomic_long_t data;
struct list_head entry;
work_func_t func;
};
a, 初始化
void work_irq_half(struct work_struct *work)
{
printk("-------%s-------------\n", __FUNCTION__);
// 表示有数据,需要去唤醒整个进程/等待队列
wake_up_interruptible(&key_dev->wq_head);
//同时设置标志位
key_dev->key_state = 1;
//发送信号
kill_fasync(&key_dev->faysnc, SIGIO, POLLIN);
}
struct work_struct mywork;
INIT_WORK(struct work_struct *work, work_func_t func);
b, 在上半部中放入到内核线程中--启动
schedule_work(&key_dev->mywork);