Linux内核中的Workqueue机制分析
1. 什么是workqueue
Linux中的workqueue(工作队列)主要是为了简化在内核创建线程而设计的。通过相应的工作队列接口,可以使开发人员只关心与特定功能相关的处理流程,而不必关心内核线程的创建、维护和销毁等工作(这样的工作对于一般人员来说是比较困难的,稍有不慎可能导致系统的崩溃),大大提高的系统的稳定性和扩展性。
我们可以通过调用workqueue的相关接口函数自动创建内核线程,此外它可以根据需求为每一个cpu核创建一个workqueue, 这对目前的多核并发提供了较好的支持。
2. workqueue的高频使用场合(尤其面试中)
Linux在处理中断的过程中,中断处理函数应尽快的完成,否则将会应用对其他中断的响应,从而影响整个系统的性能。但耗时的操作有时有必不可免,因此Linux为了解决这矛盾,将中断处理流程分成了中断上半部和中断下半部;
中断上半部: 主要完成紧急而又不耗时的工作
中断下半部:完成不紧急但比较耗时的操作。 下半部在执行过程中,中断被重新使能,因此此时可以响应新的中断,而正在执行的中断下半部被迫停止而去执行新的中断上半部,只有当没有新的中断发生时再去执行中断下半部处理流程。
这与workqueue(工作队列)有什么关系呢?
原因就在于workqueue经常用来处理中断下半部操作,相对于软中断和tasklet,这样做的优势有很多:
- workqueue是一个内核进程,工作在进程上下文,可以使用调度器;而软中断和tasklet则工作在中断上下文,不能使用引起调度的函数或者接口。
- workqueue作为一个单独的内核线程,可以进行延时或者休眠。
3. workqueue在内核中的组织结构
在workqueue中,涉及的比较重要的数据结构有三个,其组织关系可以如下图表示:
(这只是个简单的缩略图,其结构体其他成员未标出)
3.1 workqueue_struct 结构
struct workqueue_struct {
struct cpu_workqueue_struct *cpu_wq; /*用于挂接不同cpu核上的同一类工作队列*/
struct list_head list;
const char *name; /*工作队列名字*/
int singlethread; /*是否为单线程而不论有一个cpu核*/
int freezeable; /* Freeze threads during suspend */
};
3.2 cpu_workqueue_struct 结构
/*
* The per-CPU workqueue (if single thread, we always use the first
* possible cpu).
*/
struct cpu_workqueue_struct {
spinlock_t lock;
struct list_head worklist; /*工作列表,添加工作时放入此链表中*/
wait_queue_head_t more_work;
struct work_struct *current_work;/*从工作链表中取出的正在执行的工作*/
struct workqueue_struct *wq;/*指向上一级workqueue_struct目录*/
struct task_struct *thread; /*创建的线程*/
int run_depth; /* Detect run_workqueue() recursion depth */
}
3.3 work_struct 结构
workqueue中,三个结构体中,只有这个结构才是与开发常用的,上述两个数据结构及操作接口可以直接使用而无需我们进行开发或者修改。
struct work_struct {
atomic_long_t data; /*传入的数据*/
#define WORK_STRUCT_PENDING 0 /* T if work item pending execution */
#define WORK_STRUCT_FLAG_MASK (3UL)
#define WORK_STRUCT_WQ_DATA_MASK (~WORK_STRUCT_FLAG_MASK)
struct list_head entry;
work_func_t func; /*完成工作的函数,如果需要参数,则使用data进行传递*/
};
4. workqueue的函数接口
序号 | 接口函数 | 说明 |
---|---|---|
1 | create_workqueue | 用于创建一个workqueue队列,为系统中的每个CPU都创建一个内核线程。输入参数:@name:workqueue的名称 |
2 | create_singlethread_workqueue | 用于创建workqueue,只创建一个内核线程。 输入参数:@name:workqueue名称 |
3 | destroy_workqueue | 释放workqueue队列。输入参数:@ workqueue_struct:需要释放的workqueue队列指针 |
4 | schedule_work | 调度执行一个具体的任务,执行的任务将会被挂入Linux系统提供的workqueue——keventd_wq输入参数:@ work_struct:具体任务对象指针 |
5 | schedule_delayed_work | 延迟一定时间去执行一个具体的任务,功能与schedule_work类似,多了一个延迟时间,输入参数:@work_struct:具体任务对象指针; @delay:延迟时间 |
6 | queue_work | 调度执行一个指定workqueue中的任务。输入参数:@ workqueue_struct:指定的workqueue指针**@work_struct**:具体任务对象指针 |
7 | queue_delayed_work | 延迟调度执行一个指定workqueue中的任务,功能与queue_work类似,只是多了一个delay参数。 |
下面简单介绍下上述几个接口的实现逻辑:
5. workqueue的初始化
6. 将工作添加到workqueue中
7.workqueue的销毁
Linux内核中的Workqueue机制分析的更多相关文章
- Linux内核中的信号机制--一个简单的例子【转】
本文转载自:http://blog.csdn.net/ce123_zhouwei/article/details/8562958 Linux内核中的信号机制--一个简单的例子 Author:ce123 ...
- Linux内核中SPI总线驱动分析
本文主要有两个大的模块:一个是SPI总线驱动的分析 (研究了具体实现的过程): 另一个是SPI总线驱动的编写(不用研究具体的实现过程). 1 SPI概述 SPI是英语Serial Peripheral ...
- 浅析linux内核中的idr机制
idr在linux内核中指的就是整数ID管理机制,从本质上来说,这就是一种将整数ID号和特定指针关联在一起的机制.这个机制最早是在2003年2月加入内核的,当时是作为POSIX定时器的一个补丁.现在, ...
- 再谈Linux内核中的RCU机制
转自:http://blog.chinaunix.net/uid-23769728-id-3080134.html RCU的设计思想比较明确,通过新老指针替换的方式来实现免锁方式的共享保护.但是具体到 ...
- Linux内核中TCP SACK机制远程DoS预警通告
漏洞描述 2019年6月18日,RedHat官网发布报告:安全研究人员在Linux内核处理TCP SACK数据包模块中发现了三个漏洞,CVE编号为CVE-2019-11477.CVE-2019-114 ...
- armv8(aarch64)linux内核中flush_dcache_all函数详细分析【转】
转自:http://blog.csdn.net/qianlong4526888/article/details/12062809 版权声明:本文为博主原创文章,未经博主允许不得转载. /* * __ ...
- linux内核中sys_poll()的简化分析
app:poll or select; kernel: sys_poll(); do_sys_poll(struct pollfd __user *ufds, unsigned int nfds,st ...
- armv8(aarch64)linux内核中flush_dcache_all函数详细分析
/* * __flush_dcache_all() * Flush the wholeD-cache. * Corrupted registers: x0-x7, x9-x11 */ ENTRY( ...
- Linux内核中锁机制之RCU、大内核锁
在上篇博文中笔者分析了关于完成量和互斥量的使用以及一些经典的问题,下面笔者将在本篇博文中重点分析有关RCU机制的相关内容以及介绍目前已被淘汰出内核的大内核锁(BKL).文章的最后对<大话Linu ...
随机推荐
- TypeScript学习笔记(四)装饰器
目录 一.装饰器的作用 二.类装饰器 1. 普通装饰器 为类扩展属性和方法 使用装饰器修改属性和重写方法 2. 装饰器工厂 三.属性装饰器 四.方法装饰器 使用方法装饰器对方法进行扩展 五.方法参数装 ...
- 使用simg2img win提取安卓官方ROM包中独立的系统软件
一.背景 今天是七夕情人节诶,但是与我一只单身老狗有啥关系呢?一大早发现手机系统更新了(MIUI12.5 增强版),但是更新完后感觉充电速度不是很妙(你们懂得),为了恢复之前的充电速度,首先想到将手机 ...
- 关于:org.apache.catalina.connector.ClientAbortException及getOutputStream() has already been called for this response的异常处理
1.异常场景: 在进行将数据用word导出或者Excel导出的时候.抛出的异常getOutputStream() has already been called for this response 导 ...
- SpringBoot开发八-会话管理
需求介绍-会话管理 利用Cookie和Seesion使得HTTP变成有会话的连接,写几个实例演示一下 代码实现 先写个例子,表示客户端第一次访问服务器,服务器端创建一个Cookie发送给客户端. 不管 ...
- GraphQL API vs REST API
REST是构建API的一种流行方法,而且比GraphQL应用更广泛,让我们看看GraphQL和REST的区别. Rest是一个概念 REST是一个事实上的架构标准,但它实际上没有规范,有大量的非官方定 ...
- [源码解析] 机器学习参数服务器Paracel (3)------数据处理
[源码解析] 机器学习参数服务器Paracel (3)------数据处理 目录 [源码解析] 机器学习参数服务器Paracel (3)------数据处理 0x00 摘要 0x01 切分需要 1.1 ...
- 初探 Python Flask+Jinja2 SSTI
初探 Python Flask+Jinja2 SSTI 文章首发安全客:https://www.anquanke.com/post/id/226900 SSTI简介 SSTI主要是因为某些语言的框架中 ...
- MATLAB—二维函数可视化
本文主要总结一下MATLAB的一些常用二维绘图指令. 文章目录 一.plot绘图指令 1.离散数据点形设置值 2.连续线型设置值 3.颜色设置值 4.常用属性和属性值 5.例题 二.subplot绘图 ...
- spring-boot 2.5.4,nacos 作为配置、服务发现中心,Cloud Native Buildpacks 打包镜像,GitLab CI/CD
spring-boot 2.5.4,nacos 作为配置.服务发现中心,Cloud Native Buildpacks 打包镜像,GitLab CI/CD 本文主要介绍 Java 通过 Cloud N ...
- NOIP 模拟 $36\; \rm Dove 打扑克$
题解 \(by\;zj\varphi\) 引理 对于一个和为 \(n\) 的数列,不同的数的个数最多为 \(\sqrt n\) 证明: 一个有 \(n\) 个不同的数的数列,和最小就是 \(n\) 的 ...