一、概述
使用缺省工作队列,使用系统工作队列要求工作不能一直占用,可能导致系统其他任务无法执行,且无法取消暂停。系统workqueue中相同work串行处理,不同work可同时处理。
二、函数接口
struct work_struct wq
INIT_WORK(_work, _func)
schedule_work();
schedule_work_on();
INIT_DELAYED_WORK(_work, _func)
int schedule_delayed_work(struct work_struct *work, unsigned long delay);
bool schedule_delayed_work_on(int cpu, struct delayed_work *dwork, unsigned long delay)
void flush_scheduled_work(void); 刷新缺省工作队列。此函数会一直等待,直到队列中的所有工作都被执行
bool cancel_work_sync(struct work_struct *work);
int cancel_delayed_work(struct work_struct *work); 取消延迟工作
bool cancel_delayed_work_sync(struct delayed_work *dwork);
新建工作队列,不建议采用:
struct workqueue_struct
struct workqueue_struct *create_workqueue(const char *name);
int queue_work(struct workqueue_struct *wq, struct work_struct *work);
bool queue_work_on(int cpu, struct workqueue_struct *wq, struct work_struct *work);
bool queue_work_on(int cpu, struct workqueue_struct *wq, struct work_struct *work);
int queue_delayed_work(struct workqueue_struct *wq, struct work_struct *work, unsigned long delay);
void flush_workqueue(struct workqueue_struct *wq);
void destroy_workqueue(struct workqueue_struct *wq);
三、代码示例
#include <linux/device.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/string.h>
#include <linux/list.h>
#include <linux/types.h>
#include <linux/delay.h>
#include <linux/kobject.h>
#include <linux/sysfs.h>
#include <linux/workqueue.h>
MODULE_AUTHOR("hpz");
MODULE_LICENSE("Dual BSD/GPL");
#define hp_prt(fmt, arg...) printk("[%s,%d] "fmt, __FUNCTION__, __LINE__, ##arg);
static struct work_struct sys_wk;
static struct work_struct hp_wk;
static struct work_struct hp_wk1;
static struct delayed_work sys_delay_wk;
struct workqueue_struct *hp_wq;
struct workqueue_struct *hp_wq1;
void hp_work_fun(struct work_struct *work)
{
if(work == &hp_wk) {
// while(1) {
hp_prt("self workqueque work enter! %d\n", pid_nr(get_task_pid(current, PIDTYPE_PID)));
msleep(5000);//mdelay
// }
}
if(work == &hp_wk1) {
// while(1) {
hp_prt("self workqueque11 work enter! %d\n", pid_nr(get_task_pid(current, PIDTYPE_PID)));
msleep(5000);
// }
}
if(work == &sys_wk) {
// while(1) {
hp_prt("system workqueque work enter!%d\n", pid_nr(get_task_pid(current, PIDTYPE_PID)));
// cancel_delayed_work(&sys_delay_wk);
// return ;
msleep(5000);
// }
}
if(work == (struct work_struct *)&sys_delay_wk) {
// while(1) {
hp_prt("system workqueque delayed work enter! %d\n", pid_nr(get_task_pid(current, PIDTYPE_PID)));
msleep(5000);
// }
}
return ;
}
static int code_case_workqeue_init(void)
{
hp_prt(" enter!\n");
hp_wq = create_workqueue("hpz");
hp_wq1 = alloc_workqueue("hpz_zhap", 0, 0);
INIT_WORK(&hp_wk, hp_work_fun);
INIT_WORK(&hp_wk1, hp_work_fun);
//queue_work(hp_wq, &hp_wk);
queue_work_on(2, hp_wq, &hp_wk);
// queue_work_on(4, hp_wq1, &hp_wk1);
INIT_WORK(&sys_wk, hp_work_fun);
schedule_work_on(3, &sys_wk);
schedule_work_on(3, &hp_wk1);
INIT_DELAYED_WORK(&sys_delay_wk, hp_work_fun);
schedule_delayed_work(&sys_delay_wk, 5000);
return 0;
}
static void code_case_workqeue_exit(void)
{
hp_prt(" enter!\n");
cancel_work_sync(&sys_wk);
hp_prt("cancel_work_sync enter!\n");
flush_scheduled_work();
hp_prt("flush_scheduled_work complete!\n");
flush_workqueue(hp_wq);
hp_prt("flush_workqueue complete!\n");
destroy_workqueue(hp_wq);
}
module_init(code_case_workqeue_init);
module_exit(code_case_workqeue_exit);