链接:https://pan.baidu.com/s/1V0E9IHSoLbpiWJsncmFgdA?pwd=1688
提取码:1688
工作队列的作用:用来代替任务队列.
他们允许内核函数(像可延迟的函数)激活,而且稍后由一种叫做工作者线程的特殊内核线程来执行.
和可延迟函数的不同:
可延迟函数运行在中断上下文中,不一定在创建它的进程当中运行.
工作队列中的函数运行在进程上下文中.(但是由内核线程来执行)
执行可阻塞函数的唯一方式是在进程上下文中运行.
相同点:
可延迟函数运行时不可能有任何正在运行的进程,而工作队列是由内核线程来执行的,所以他们都不能访问用户态地址空间.
工作队列的使用.
1。创建
2。提交队列
3。删除
创建:
创建分为工作队列的创建和工作函数(任务)的创建.
(1) 工作队列的创建需要有其描述符,它的数据结构是 workqueue_struct.该结构定义在
struct workqueue_struct *create_workqueue(const char *name);
struct workqueue_struct * workqueue_singlethread_workqueue(const char *name);
他们的区别在于实际处理器的多少,如果是单核处理器的话,他们毫无区别.
因为每个工作队列都有一个或多个(多核处理器)专用的进程(内核线程),这些进程运行提交到该工作队列函数.
create_workqueue内核会在系统中的每个处理器上为该工作队列创建专用的线程.这样,如果工作队列足够多的话,可能对系统的性能有所杀伤,而create_singlethread_workqueue则只会创建一个专用的线程.所以,如果单个工作线程足够使用,推荐使用第二个函数来创建工作队列.
同样的,工作任务的创建也需要有其描述符,它的数据结构是work_struct.内核同样为我们创建好了几个宏来方便的创建它.
DECLARE_WORK(name,void(*function)(void *),void *data);
用于在内核编译时使用.
INIT_WORK(struct work_struct *work,void(*function)(void *),void *data);
用于在系统运行时创建.首次创建时使用它.
PREPARE_WORK(struct work_struct *work,void(*function)(void *),void *data);
用于在系统运行时创建.没有INIT_WORK初始化彻底,因为它不会初始化用来将work_struct结构连接到工作队列的指针.如果结构已经被提交到工作队列,而只是需要修改该结构,则应该使用PREPARE_WORK而不是INIT_WORK.
提交:
如果要将工作提交到工作队列,则可使用如下两个函数之一:
int queue_work(struct workqueue_struct *queue,struct work_struct *work);
int queue_delayed_work(struct workqueue_struct *queue,struct work_struct *work,unsigned long delay);
它们都会将work添加到给定的queue.但是如果使用queue_delayed_work,则实际工作至少会在经过指定的jiffies(由delay指定)之后才会执行.如果工作被成功添加到队列,则上述函数的返回值为1,返回值为非零意味着给定的work_struct结构已经等待在该队列中,从而不能两次加入该队列.
删除:
结束对工作队列的使用后,可调用下面的函数释放相关资源.
void destroy_workqueue(struct workqueue_struct *queue);