struct work_struct{ unsigned long pending; struct list_head entry; void (*func) (void *); void *data; void *wq_data; struct timer_list timer; };
这时,&work指向的work_struct直到delay指定的时钟节拍用完以后才会执行。
6 、创建自己的工作队列
使用内核提供的共享列队,列队是保持顺序执行的,做完一个工作才做下一个,如果一个工作内有耗时大的处理如阻塞等待信号或锁,那么后面的工作都不会执行。如果你不喜欢排队或不好意思让别人等太久,那么可以创建自己的工作者线程,所有工作可以加入自己创建的工作列队,列队中的工作运行在创建的工作者线程中。
创建工作列队使用3个宏 成功后返回workqueue_struct *指针,并创建了工作者线程。三个宏主要区别在后面两个参数singlethread和freezeable,singlethread为0时会为每个cpu上创建一个工作者线程,为1时只在当前运行的cpu上创建一个工作者线程。freezeable会影响内核线程结构体thread_info的PF_NOFREEZE标记
if (!cwq->freezeable)
current->flags |= PF_NOFREEZE;
set_user_nice(current, -5);
在线程函数内设置了测试点如下
if (cwq->freezeable)
try_to_freeze();
如果设置了PF_NOFREEZE这个flag,那么系统挂起时候这个进程不会被挂起。
主要函数
#define create_workqueue(name) __create_workqueue((name), 0, 0) //多处理器时会为每个cpu创建一个工作者线程
#define create_freezeable_workqueue(name) __create_workqueue((name), 1, 1) //只创建一个工作者线程,系统挂起是线程也挂起
#define create_singlethread_workqueue(name) __create_workqueue((name), 1, 0) //只创建一个工作者线程,系统挂起是线程线程不挂起
以上三个宏调用__create_workqueue函数定义
extern struct workqueue_struct *__create_workqueue(const char *name,int singlethread, int freezeable);
释放创建的工作列队资源
void destroy_workqueue(struct workqueue_struct *wq)
延时调用指定工作列队的工作
queue_delayed_work(struct workqueue_struct *wq,struct delay_struct *work, unsigned long delay)
取消指定工作列队的延时工作
cancel_delayed_work(struct delay_struct *work)
将工作加入工作列队进行调度
queue_work(struct workqueue_struct *wq, struct work_struct *work)
等待列队中的任务全部执行完毕。
void flush_workqueue(struct workqueue_struct *wq);
#include <linux/module.h> #include <linux/init.h> #include <linux/workqueue.h> static struct workqueue_struct *queue = NULL; static struct work_struct work; static void work_handler(struct work_struct *data) { printk(KERN_ALERT "work handler function./n"); } static int __init test_init(void) { queue = create_singlethread_workqueue("helloworld"); if (!queue) goto err; INIT_WORK(&work, work_handler); schedule_work(&work); return 0; err: return -1; } static void __exit test_exit(void) { destroy_workqueue(queue); } MODULE_LICENSE("GPL"); module_init(test_init); module_exit(test_exit);