queue_delayed_work和queue_work
一、参考文献:
1)
queue_delayed_work的使用过程如下:
--> 定义workqueue: struct workqueue_struct *test_workqueue; // 定义在: kernel/workqueue.c
--> 定义workqueue要做的delayed工作:struct delayed_work test_delayed_work; // 定义在: include/linux/workqueue.h
--> 初始化workqueue:INIT_DELAYED_WORK(test_workqueue, test_delayed_work); // 定义在:include/linux/workqueue.h
--> 创建线程queue并加以名字:test_workqueue = create_singlethread_workqueue("name_of_this_queue");
--> 运行queue:queue_delayed_work(test_workqueue, test_delayed_work, delay_time); // 定义在:kernel/workqueue.c, 其中delay_time是延迟多少时间来运行queue。
注: 在delayed_work中一定要再次将delayed_workqueue加入queue中,即再次运行queue_delayed_work。否则,此queue只运行一次。
2)
一个INIT_WORK()对应queue_work、schedule_work(),一个INIT_DELAYED_WORK()对应queue_delayed_work、schedule_delayH
后者就是专门用于可以有延时的,而前者就是没有延时的
关于工作队列机制,咱们还会用到另外两个函数,它们是cancel_delayed_work(struct delayed_work *work)和flush_scheduled_work().其中
cancel_delayed_work()的意思不言自明,对一个延迟执行的工作来说,这个函数的作用是在这个工作还未执行的时候就把它给取消掉.而flush_scheduled_work()的作用,是为了防止有竞争条件的
(例:比如说它先想好了,下午3点执行队列里的第N个成员,可是您突然把第N-1个成员给取走了,那您说这是不是得出错?所以,为了防止您这种唯恐天下不乱的人做出冒天下之大不韪的事
3)
内核队列、定时器、阻塞、休眠
API:
1) INIT_WORK(_work, _func)
初始化指定工作,目的是把用户指定的函数_func赋给work_struct的func。
2) int schedule_work(struct work_struct *work)------>> queue_work
对工作进行调度,即把给定工作的处理函数提交给缺省的工作队列和工作者线程。工作者线程本质上是一个普通的内核线程,在默认情况下,每个CPU均有一个类型为“events”的工作者线程,当调用schedule_work时,这个工作者线程会被唤醒去执行工作链表上的所有工作。
3) int schedule_delayed_work(struct work_struct *work, unsigned long delay) ---> queue_delayed_work --> queue_work
延迟执行工作,与schedule_work类似。
4) void flush_scheduled_work(void)
刷新缺省工作队列。此函数会一直等待,直到队列中的所有工作都被执行。
5) int cancel_delayed_work(struct work_struct *work)
flush_scheduled_work并不取消任何延迟执行的工作,因此,如果要取消延迟工作,应该调用cancel_delayed_work。
4)
相对于create_singlethread_workqueue, create_workqueue同样会分配一个wq的工作队列,但是不同之处在于,对于多CPU系统而言,对每一个CPU,都会为之
创建一个per-CPU的cwq结构,对应每一个cwq,都会生成一个新的worker_thread进程。但是当用queue_work向cwq上提交work节点时,是哪个CPU调用该函数,那么便向该CPU对应的cwq上的worklist上增加work节点。
二、简略程序:
1)queue_work
create_workqueue("goodix_wq");//加载ko时init或probe时初始化
INIT_WORK(&ts->work, goodix_ts_work_func);//初始化工作队列
queue_work(goodix_wq, &ts->work);//此处需要request_irq中断触发或者是timer定时器触发, 调度执行并不等于立刻执行。而是指示
//worker_thread在下次处理工作队列的时候执行该工作;
destroy_workqueue(goodix_wq);//卸载ko退出或remove时注销
2)queue_work
create_singlethread_workqueue("proximity");///加载ko时init或probe时初始化 //单线程,此处也可使用create_workqueue();如前文引文4)内容
INIT_DELAYED_WORK(&ip->work, rohm_proximity_work));//初始化工作队列
queue_delayed_work(data->work_queue, &data->work,msecs_to_jiffies(ms));//同前面queue_work区别在于:自带延时功能,即定时器功能
//调用此函数后,经过ms时间后就会自动进入工作队伍函数,此处为rohm_proximity_work()