工作队列
时间:2022-07-22
本文章向大家介绍工作队列,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
简介
工作队列就是内核中延后工作的一种方式,延后工作在无数场景都可以反复调度使用。
数据结构组成
/* @data: func的参数
* @entry: 连接工作的指针
* @func: 工作处理函数
*/
struct work_struct {
atomic_long_t data;
struct list_head entry;
work_func_t func;
#ifdef CONFIG_LOCKDEP
struct lockdep_map lockdep_map;
#endif
};
使用流程
API 路径:kernel/kernel/workqueue.c; kernel/include/linux/workqueue.h
创建一个工作队列: a. 创建一个服务于单个CPU的工作队列
/* @name:队列名
* RETURNS: Pointer to the allocated workqueue on success, %NULL on failure.
*/
create_singlethread_workqueue(name);
b. 在每一个CPU上创建一个工作队列
/* @name:队列名
* RETURNS: Pointer to the allocated workqueue on success, %NULL on failure.
*/
create_workqueue(name);
相对于create_singlethread_workqueue, create_workqueue同样会分配一个wq的工作队列,但是不同之处在于,对于多CPU系统而言,对每一个CPU,都会为之创建一个per-CPU的cwq结构,对应每一个cwq,都会生成一个新的worker_thread进程。但是当用queue_work向cwq上提交work节点时,是哪个CPU调用该函数,那么便向该CPU对应的cwq上的worklist上增加work节点。
初始化工作项 a. 动态注册
//kernel/include/linux/workqueue.h
INIT_WORK(_work, _func)
b. 静态注册
//kernel/include/linux/workqueue.h
DECLARE_WORK(_work, _func)
使用静态注册可以省略定义_work,且DECLARE_WORK需要放在代码头部预处理。
运行指定工作项 a. 自定义队列运行queue_work
/* @wq: workqueue to use
* @work: work to queue
* Returns %false if @work was already on a queue, %true otherwise.
*/
queue_work(struct workqueue_struct *wq, struct work_struct *work)
b. 系统工作队列运行schedule_work
/* @work: 工作项
* Returns %false if @work was already on the kernel-global workqueue and %true otherwise.
*/
schedule_work(struct work_struct *work)
queue_work,使用自定义队列运行工作项 schedule_work,调用系统的工作队列运行工作项。
小结:
一般情况下,需要指定情况多次重复调用工作项,选择定时器+queue_work。如果是指定情况下调用一次,则使用schedule_work,利用系统的工作队列执行需要的工作项。
使用流程
1.声明变量
struct test_work_dev work_dev;
static struct workqueue_struct * test1_workqueue = NULL;
2.声明回调函数
void test1_callback(struct work_struct *work);
3.初始化队列项
#if defined (DECLARE_WORK_SUPPORT )
static DECLARE_WORK(test1_item, (void *) test1_callback);
#endif
#if !defined(DECLARE_WORK_SUPPORT)
static struct work_struct test1_item;
test1_workqueue = create_singlethread_workqueue("test1_wq");
INIT_WORK(&test1_item, test1_callback);
#endif
4.定义回调
void test1_callback(struct work_struct *work)
{
printk("test1_callback!");
}
5.调度
queue_work(test1_workqueue, &test1_item);
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 一篇带你看懂Flutter叠加组件Stack
- Flutter 拖拽排序组件 ReorderableListView
- 女神节 | 程序员如何低调而又不失逼格
- Flutter 拖拽控件Draggable看这一篇就够了
- 面试官:你精通多少种语言的Hello World?
- Flutter 裁剪类组件 最全总结
- Flutter Form表单控件超全总结
- 你知道吗,Flutter内置了10多种Button控件
- Flutter 日期时间DatePicker控件及国际化
- 强大的Flutter App升级功能
- 你知道吗,Flutter内置了10多种show
- 还记得第一个看到的Flutter组件吗?
- 150多个Flutter组件详细介绍送给你
- Flutter 学习路线图
- Flutter 强大的MediaQuery控件