Linux 内核工作队列之work_struct 学习总结
前言
编写Linux驱动的时候对于work_struct的使用还是很普遍的,很早之前就在阅读驱动源码的时候就看到了它的踪影,根据其命名大概知道了它的具体作用,但是仍然不知所以,同时,伴随出现的还有delayed_work以及workqueue_struct,抱着知其然并知其所以然的态度,在这里归纳总结一下work_struct,以及如何在驱动中使用,因为工作队列相对来说比较复杂,篇幅和能力有限,只能介绍相对重要的部分。
workqueue
内核里一直运行类似worker thread,它会对工作队列中的work进行处理,大致的工作流程原理可以参考下图所示;

在这里的work则是work_struct变量,并且绑定一个执行函数——typedef void (*work_func_t)(struct work_struct *work);。在worker thread中会对非空的工作队列进行工作队列的出队操作,并运行work绑定的函数。
work_struct
work_struct的数据结构如下,暂时我们还无法关注其原理,只关注如何去开启一个work
#include <linux/include/workqueue.h>
typedef void (*work_func_t)(struct work_struct *work);
struct work_struct {
atomic_long_t data;
struct list_head entry;
work_func_t func;
#ifdef CONFIG_LOCKDEP
struct lockdep_map lockdep_map;
#endif
};
通过数据结构可以知道,每当我们定义一个work_struct变量的时候,需要绑定一个work_func_t类型的函数指针。
| 函数 | 功能 |
|---|---|
| INIT_WORK(_work, _func) | 初始化一个work |
| INIT_WORK_ONSTACK(_work, _func) | 在栈上初始化一个work |
| flush_work(struct work_struct *work); | 销毁一个work |
| schedule_work(struct work_struct *work) | 调度一个work开始运行 |
例程
下面写了 一个demo,模块初始化之后会每隔5秒调度work开始运行,最终demo_work_func会运行规定的次数,并打印传递的参数和进程信息。
#include <linux/init.h>
#include <linux/module.h>
#include <linux/time.h>
#include <linux/jiffies.h>
#include <linux/workqueue.h>
#include <linux/slab.h> //kmalloc kfree
#include <linux/sched.h>
#include <linux/delay.h>
static char data[] = "test for demo work";
struct work_ctx{
struct work_struct real_work;
char *str;
int arg;
}work_ctx;
struct work_ctx *demo_work;
static void demo_work_func(struct work_struct *work){
struct work_ctx *temp_work = container_of(work,struct work_ctx,real_work);
printk(KERN_INFO "[work]=> PID: %d; NAME: %s\n", current->pid, current->comm);
printk(KERN_INFO "[work]=> sleep 1 seconds\n");
set_current_state(TASK_INTERRUPTIBLE);
schedule_timeout(1 * HZ); //Wait 1 seconds
printk(KERN_INFO "[work]=> data is: %d %s\n", temp_work->arg,temp_work->str);
}
static int __init demo_thread_init(void){
int count = 10;
demo_work = kmalloc(sizeof(*demo_work),GFP_KERNEL);
INIT_WORK(&demo_work->real_work, demo_work_func);
demo_work->str = data;
while(count--){
msleep(5000);
demo_work->arg = count;
schedule_work(&demo_work->real_work);
}
return 0;
}
module_init(demo_thread_init);
static void __exit demo_thread_exit(void){
flush_work(&demo_work->real_work);
kfree(demo_work);
}
module_exit(demo_thread_exit);
MODULE_LICENSE("GPL");
运行结果
[ 8.500146] [work]=> PID: 37; NAME: kworker/0:1
[ 8.500216] [work]=> sleep 1 seconds
[ 9.499783] [work]=> data is: 9 test for demo work
[ 13.503165] [work]=> PID: 37; NAME: kworker/0:1
[ 13.503213] [work]=> sleep 1 seconds
[ 14.503122] [work]=> data is: 8 test for demo work
[ 18.506493] [work]=> PID: 37; NAME: kworker/0:1
[ 18.506534] [work]=> sleep 1 seconds
[ 19.506460] [work]=> data is: 7 test for demo work
[ 23.509833] [work]=> PID: 37; NAME: kworker/0:1
[ 23.509874] [work]=> sleep 1 seconds
[ 24.510060] [work]=> data is: 6 test for demo work
[ 28.513161] [work]=> PID: 37; NAME: kworker/0:1
[ 28.513206] [work]=> sleep 1 seconds
[ 29.513121] [work]=> data is: 5 test for demo work
[ 33.516502] [work]=> PID: 37; NAME: kworker/0:1
[ 33.516545] [work]=> sleep 1 seconds
[ 34.516452] [work]=> data is: 4 test for demo work
[ 38.519819] [work]=> PID: 37; NAME: kworker/0:1
[ 38.519860] [work]=> sleep 1 seconds
[ 39.519782] [work]=> data is: 3 test for demo work
[ 43.523151] [work]=> PID: 37; NAME: kworker/0:1
[ 43.523191] [work]=> sleep 1 seconds
[ 44.523117] [work]=> data is: 2 test for demo work
[ 48.526495] [work]=> PID: 37; NAME: kworker/0:1
[ 48.526542] [work]=> sleep 1 seconds
[ 49.526444] [work]=> data is: 1 test for demo work
[ 53.539699] [work]=> PID: 37; NAME: kworker/0:1
[ 53.539763] [work]=> sleep 1 seconds
[ 54.542925] [work]=> data is: 0 test for demo work
参考
https://www.oreilly.com/library/view/understanding-the-linux/0596005652/ch04s08.html
https://kukuruku.co/post/multitasking-in-the-linux-kernel-workqueues/
Linux 内核工作队列之work_struct 学习总结的更多相关文章
- LINUX内核分析第一周学习总结——计算机是如何工作的
LINUX内核分析第一周学习总结——计算机是如何工作的 张忻(原创作品转载请注明出处) <Linux内核分析>MOOC课程http://mooc.study.163.com/course/ ...
- LINUX内核分析第二周学习总结——操作系统是如何工作的
LINUX内核分析第二周学习总结——操作系统是如何工作的 张忻(原创作品转载请注明出处) <Linux内核分析>MOOC课程http://mooc.study.163.com/course ...
- LINUX内核分析第四周学习总结——扒开系统调用的“三层皮”
LINUX内核分析第四周学习总结--扒开系统调用的"三层皮" 标签(空格分隔): 20135321余佳源 余佳源 原创作品转载请注明出处 <Linux内核分析>MOOC ...
- linux内核分析第四周学习笔记
linux内核分析第四周学习笔记 标签(空格分隔): 20135328陈都 陈都 原创作品转载请注明出处 <Linux内核分析>MOOC课程http://mooc.study.163.co ...
- Linux内核分析第二周学习笔记
linux内核分析第二周学习笔记 标签(空格分隔): 20135328陈都 陈都 原创作品转载请注明出处 <Linux内核分析>MOOC课程http://mooc.study.163.co ...
- linux内核分析第一周学习笔记
linux内核分析第一周学习笔记 标签(空格分隔): 20135328陈都 陈都 原创作品转载请注明出处 <Linux内核分析>MOOC课程http://mooc.study.163.co ...
- Linux内核的ioctl函数学习
Linux内核的ioctl函数学习 来源:Linux公社 作者:Linux 我这里说的ioctl函数是在驱动程序里的,因为我不知道还有没有别的场合用到了ioctl, 所以就规定了我们讨论的范围.为什 ...
- Linux内核分析第一周学习博客 --- 通过反汇编方式学习计算机工作过程
Linux内核分析第一周学习博客 通过反汇编方式学习计算机工作过程 总结: 通过这次对一个简单C程序的反汇编学习,我了解到计算机在实际工作工程中要涉及大量的跳转指针操作.计算机通常是顺序执行一条一条的 ...
- Linux内核分析第二周学习博客——完成一个简单的时间片轮转多道程序内核代码
Linux内核分析第二周学习博客 本周,通过实现一个简单的操作系统内核,我大致了解了操作系统运行的过程. 实验主要步骤如下: 代码分析: void my_process(void) { int i = ...
随机推荐
- I. 蚂蚁上树
蚂蚁上树(Sauteed Vermicelli with minced Pork),又名肉末粉条,是四川省及重庆市的特色传统名菜之一.因肉末贴在粉丝上,形似蚂蚁爬在树枝上而得名.这道菜具体的历史,已不 ...
- tortoise 设置beyond Compare比较工具
1.桌面右击tortoiseSVN->setting->Diff Viewer面板,选择external,选中beyond Compare路径
- async,await执行流看不懂?看完这篇以后再也不会了
昨天有朋友在公众号发消息说看不懂await,async执行流,其实看不懂太正常了,因为你没经过社会的毒打,没吃过牢饭就不知道自由有多重要,没生过病就不知道健康有多重要,没用过ContinueWith就 ...
- 基于thinkphp3.2.3开发的CMS内容管理系统 - ThinkPHP框架
基于thinkphp3.2.3开发的CMS内容管理系统 thinkphp版本:3.2.3 功能: --分类栏目管理 --文章管理 --用户管理 --友情链接管理 --系统设置 目前占时这些功能,更多功 ...
- [linux] 小问题:管道符,换行问题等;[nginx]启动,重启,关闭命令;以及升级nginx切换命令
Lniux换行问题 后面回车不会马上执行本条命令而是换行继续. : 是运行完前面就继续后面的, && 同样是前面正确就运行后面, || 是前面运行不正确就运行后面. | 管道符“|”将 ...
- Java集合案例(产生不重复随机数)
获取10个1-20之间的随机数,要求不能重复 用数组实现,但是数组的长度是固定的,长度不好确定.所以我们使用集合实现. 分析:A:创建产生随机数的对象B:创建一个存储随机数的集合C:定义一个统计变量. ...
- Java多台中成员访问特点
多态中的成员访问特点: A:成员变量 编译看左边,运行看左边 B:构造方法 创建子类对象的时候,访问父类的构造方法,对父类的数据进行初始化 C:成员方法 编译看左边,运行看右边.//因为调用对象时,子 ...
- 干货!Python中字符串、列表、元祖、字典,集合之间的转换
一.字符串的转化 1.字符串转换成列表 字符串转换成list 的时候,str可以作为迭代对象,直接放入:也可以使用split对字符串进行切割.然后返回list s = '1a1b1c' print(l ...
- Python 替换文本中的某些词语
https://stackoverflow.com/questions/39086/search-and-replace-a-line-in-a-file-in-python from tempfil ...
- NTSTATUS code 和 Windows 系统错误码 的对应关系
出处:https://github.com/dokan-dev/dokany/blob/master/dokan/ntstatus.i case EPT_S_CANT_CREATE: return E ...