kernel 使用了很多工作队列。了解历史更好的理解INIT_WORK 参数
1- old kernel(2.6 之前) 如何使用INIT_WORK
#define INIT_WORK(_work, _func, _data) \
do { \
INIT_LIST_HEAD(&(_work)->entry); \
(_work)->pending = 0; \
PREPARE_WORK((_work), (_func), (_data)); \
init_timer(&(_work)->timer); \
} while (0)
#define PREPARE_WORK(_work, _func, _data) \
do { \
(_work)->func = _func; \
(_work)->data = _data; \
} while (0)
_work 实际就是
struct work_struct {
unsigned long pending;
struct list_head entry;
void (*func)(void *);
void *data;
void *wq_data;
struct timer_list timer;
};
从上面可以code 定义可以看出old kernel INIT_WORK 有三个参数,如果使用了container_of是否可以省一个参数 ,答案是肯定的
2- new kernel INIT_WORK
#define INIT_WORK(_work, _func) /
do { /
(_work)->data = (atomic_long_t) WORK_DATA_INIT(); /
INIT_LIST_HEAD(&(_work)->entry); /
PREPARE_WORK((_work), (_func)); /
} while (0)
例子1
使用最新的INIT_WORK 进行举例:
2.1. 在探测函数里goodix_ts_probe初始化
INIT_WORK(&ts->work, goodix_ts_work_func);//struct work_struct work
,ts是client私有数据结构体
主要目的就是因为就算没有中断,在第一次开机时也有检测设备,所以这个任务一开始就执行,只不过到后来中断发生后就再执行.
2.2 goodix_ts_work_func 如何实现
static void goodix_ts_work_func(struct work_struct *work) {
struct goodix_ts_data *ts = container_of(work, struct goodix_ts_data, work);
}
使用container_of这个函数来求出我们的data的指针
2.3.当然你不能忘记注册你的中断函数了
request_irq(client->irq, goodix_ts_irq_handler,pdata->irq_edge ? IRQ_TYPE_EDGE_FALLING : IRQ_TYPE_EDGE_RISING,client->name, ts);
goodix_ts_irq_handler
{
schedule_work(&ts->work) //这里就wakeup了goodix_ts_work_func
}
所以用一个结构体ts就可以把中断,任务,设备名等全部囊括进来
上面的例子使用了中断,进行了work wakeup的操作。不使用中断也是可以的。
例子2:qcom log dump reg 的操作
注册init workqueue:
kernel/msm-4.9/drivers/gpu/drm/msm/sde_dbg.c
--->sde_dbg_init
--->INIT_WORK(&sde_dbg_base.dump_work, _sde_dump_work);
--->_sde_dump_work
--->_sde_dump_array
sde_evtlog_dump_all ::这里修改了log信息
叫醒:dump_work
msm-4.9/drivers/gpu/drm/msm/sde/sde_encoder_phys_vid.c
---> sde_encoder_phys_vid_prepare_for_kickoff
--->SDE_DBG_DUMP("panic");---->sde_dbg_dump[sde_dbg.c
--->schedule_work(&sde_dbg_base.dump_work);
上面可以看出,如果发生调用了SDE_DBG_DUMP,就会调用到了dump_work workqueue
3- INIT_WORK 相关的函数,如果使用到,需要细查
INIT_DELAYED_WORK //这个work_struct 只是多了timer 进行了延时
schedule_delayed_work
cancel_delayed_work
flush_scheduled_work
REF:
https://blog.csdn.net/fcf1990501/article/details/8445441
https://blog.csdn.net/bingqingsuimeng/article/details/7891157
网友评论