工作队列子系统提供了一个缺省的工作者线程,我们只要把需要推后执行的任务交给特定的通用线程就好了,缺省的工作者线程叫events/n,我们一般使用这个缺省的工作者线程,但是如果你需要在工作者线程中执行大量的处理操作,创建自己的工作者线程就更好了。系统的每个CPU都会有一个工作者线程,每个工作者线程都是由struct cpu_workqueue_struct结构体表示,而struct workqueue_struct则表示给定类型(即同类型)的所有工作者线程。
INIT_WORK(&button_dev->work, gpio_keys_report_event); //定义
static void gpio_keys_report_event(struct work_struct *work) //处理函数
{
key_values[0] = '0' ; //清除按键标识
input_report_key(channel, BTN_0, !!ev_press); //向input子系统报告按键事件
input_sync(channel); //同步操作
ev_press = 0; //清除按键值
}
schedule_work(&button_dev->work); //调度工作队列处理函数
cancel_work_sync(&button_dev->work); //删除工作队列
tasklet基于软件中断,而工作队列是靠内核线程实现的,如果你有休眠的需要,那么你使用工作队列,否则最好使用tasklet机制。为了保证共享数据,一般先得到一个锁,然后使用local_bh_disable函数禁止下半部,但local_bh_disable函数并不能禁止工作队列的执行,因为工作队列不涉及异步执行,但是由于软中断和tasklet是异步发送的,所以内核必须禁止它们。