工作队列是进程上下文,可以休眠。
系统默认的工作者线程为events,也可以创建自己的工作者线程。
1. 工作\工作队列\工作者线程关系
推后执行的任务叫作工作,work_struct
工作以队列结构组织成工作队列(workqueue),workqueue_struct
工作线程就是负责执行工作队列中的工作
2. 定义
work_struct定义在linux/workqueue.h中,实现在kernel/workqueue.c中。
struct work_struct {
unsigned long pending; /*这个工作正在等待处理吗?*/
struct list_head entry; /*连接所有工作的连表*/
void (*func)(void *);
void *data;
void *wq_data; //内部使用
struct timer_list timer; //延迟的工作队列所用到的定时器
};
这些结构被连接成连表,当一个工作者线程被唤醒时,它会执行它的连表上的所有工作。工作被执行完毕,它就将相应的work_struct对象从连表上移走。当连表上不再有对象时,它就会继续休眠。
DECLARE_WORK(name, void (*func)(void *), void *data); // 静态
INIT_WORK(struct work_struct *work, void (*func)(void *), void *data);
工作队列执行的函数原型:
void work_handler(void *data);
这个函数会有一个工作者线程执行,因此函数运行在进程上下文。默认情况下,允许先响应中断,并且不持有锁。
尽管该函数运行在进程上下文,但它不能访问用户空间,因为内核线程在用户空间没有相关的内存映射。(通常在系统调用发生时,内核会代表用户空间的进程运行,此时它才能访问用户空间,也只有此时它才会映射用户空间的内存)。
schedule_work(&work);
schedule_delayed_work(&work, delay);
create_singlethread_workqueue("helloworld"); //创建一个单线程的工作队列
//****************************************
struct work_struct mywork;
struct workqueue_struct *queue = NULL;
INIT_WORK(&mywork, work_handler);
queue = create_workqueue("newProcess");//创建多个CPU上的工作者进程
queue_work(queue, &mywork); // 把工作添加到工作队列中
schedule_work(&mywork); //调度工作
destroy_workqueue(queue);//销毁新创建的工作者进程
参考: