linux 内核工作队列技术原理

news2024/11/18 9:54:36

首先介绍一下工作队列使用的术语。

  1. work:工作,也称为工作项。
  2. work queue:工作队列,就是工作的集合, work queue 和 work 是一对多的关系。
  3. worker: 工人, 一个工人对应一个内核线程, 我们把工人对应的内核线程称为工人线程。
  4. worker_pool:工人池,就是工人的集合,工人池和工人是一对多的关系。
  5. pool_workqueue:中介,负责建立工作队列和工人池之间的关系。

工作队列和pool_workqueue 是一对多的关系, pool_workqueue 和工人池是一对一的关系。

最终的目的还是把 work( 工作 ) 传递给 worker( 工人 ) 去执行,中间的数据结构和各种关系目的是把这件事组织的更加清晰高效。

工作队列的分类有三种,分别是PerCpu, Unbound,以及ORDERED这三种类型,其实就是创建工作队列时所传的参数:WQ_UNBOUND、__WQ_ORDERED;其不同的体现主要在绑定的worker_pool的不同来提供不同的运行机制,下面就来看一下worker_pool。
    worker_pool
每个执行 work 的线程叫做 worker,一组 worker 的集合叫做 worker_pool。CMWQ 的精髓就在 worker_pool 里面 worker 的动态增减管理上 manage_workers()。
CMWQ 对 worker_pool 分成两类:
·    normal worker_pool,给通用的 workqueue 使用;
·    unbound worker_pool,给 WQ_UNBOUND 类型的的 workqueue 使用;
其中unbound worker_pool 也分成两类:
·    unbound_std_wq。每个 node 对应一个 worker_pool,多个 node 就对应多个 worker_pool;
·    ordered_wq。所有 node 对应一个 default worker_pool;
  normal worker_pool
默认 work 是在 normal worker_pool 中处理的。系统的规划是每个 CPU 创建两个 normal worker_pool:一个 normal 优先级 (nice=0)、一个高优先级 (nice=HIGHPRI_NICE_LEVEL),对应创建出来的 worker 的进程 nice 不一样。
每个 worker 对应一个 worker_thread() 内核线程,一个 worker_pool 包含一个或者多个 worker,worker_pool 中 worker 的数量是根据 worker_pool 中 work 的负载来动态增减的。
我们可以通过 ps | grep kworker 命令来查看所有 worker 对应的内核线程,normal worker_pool 对应内核线程 (worker_thread()) 的命名规则是这样的:
    snprintf(id_buf, sizeof(id_buf), "%d:%d%s", pool->cpu, id,
         pool->attrs->nice < 0  ? "H" : "");

    worker->task = kthread_create_on_node(worker_thread, worker, pool->node,
                          "kworker/%s", id_buf);
so 类似名字是 normal worker_pool:


组织图如下:

normal worker_pool

对应的拓扑图如下:

unbound worker_pool

大部分的 work 都是通过 normal worker_pool 来执行的 ( 例如通过 schedule_work()、schedule_work_on() 压入到系统 workqueue(system_wq) 中的 work),最后都是通过 normal worker_pool 中的 worker 来执行的。这些 worker 是和某个 CPU 绑定的,work 一旦被 worker 开始执行,都是一直运行到某个 CPU 上的不会切换 CPU。
unbound worker_pool 相对应的意思,就是 worker 可以在多个 CPU 上调度的。但是他其实也是绑定的,只不过它绑定的单位不是 CPU 而是 node。所谓的 node 是对 NUMA(Non Uniform Memory Access Architecture) 系统来说的,NUMA 可能存在多个 node,每个 node 可能包含一个或者多个 CPU。
unbound worker_pool 对应内核线程 (worker_thread()) 的命名规则是这样的:

    snprintf(id_buf, sizeof(id_buf), "u%d:%d", pool->id, id);

    worker->task = kthread_create_on_node(worker_thread, worker, pool->node,
                          "kworker/%s", id_buf);
so 类似名字是 unbound worker_pool:

unbound worker_pool 也分成两类:

unbound_std_wq

每个 node 对应一个 worker_pool,多个 node 就对应多个 worker_pool;

unbound worker_pool: unbound_std_wq

对应的拓扑图如下:

unbound_std_wq topology

ordered_wq

所有 node 对应一个 default worker_pool;

unbound worker_pool: ordered_wq

对应的拓扑图如下:

ordered_wq topology

整体结构图

分析总结
我们知道工作队列有三种,分别是PerCpu, Unbound,以及ORDERED这三种类型,正如之前的文档分析:
1.PerCpu的工作队列:
create_workqueue(name)
这种工作队列在queue_work的时候,首先检查当前的Cpu是哪一个,然后将work调度到该cpu下面的normal级别的线程池中运行。
注:针对PerCpu类型而言,系统在开机的时候会注册2个线程池,一个低优先级的,一个高优先级的。

2.Unbound的工作队列:
create_freezable_workqueue(name)
这种工作队列在queue_work的时候,同样首先检查当前的Cpu是哪一个,随后需要计算当前的Cpu属于哪一个Node,因为对于Unbound的工作队列而言,线程池并不是绑定到cpu的而是绑定到Node的,随后找到该Node对应的线程池中运行。需要留意的是这种工作队列是考虑了功耗的,例如:当work调度的时候,调度器会尽量的让已经休眠的cpu保持休眠,而将当前的work调度到其他active的cpu上去执行。
注:对于NUMA没有使能的情况下,所有节点的线程池都会指向dfl的线程池。

3.Ordered的工作队列:
create_singlethread_workqueue(name) 或者 alloc_ordered_workqueue(fmt,flags, args…)
这种work也是Unbound中的一种,但是这种工作队列即便是在NUMA使能的情况下,所有Node的线程池都会被指向dfl (ordered_wq)的线程池,换句话说Ordered的工作队列只有一个线程池,因为只有这样才能保证Ordered的工作队列是顺序执行的,而这也是本文分析的切入点。

有关并发问题的总结性陈述:
首先对于Ordered的工作队列(create_singlethread_workqueue,其他自定义的API则不一定了)这是严格顺序执行的,绝对不可能出现并发(无论提交给wq的是否是同一个work)。
但是对于PerCpu的工作队列(create_workqueue),其中对于提交给wq的如果是同一个work,那么也不会并发,会顺序执行。但是如果提交给wq的不是同一个work,则会在不同的cpu间并发。需要特别留意的是,其并不会在同一个CPU的不同线程间并发,这是因为create_workqueue这个API定义的max_active为1,也就意味者,当前wq只能最多在每个cpu上并发1个线程。

另外:
        if ((flags & WQ_UNBOUND) && max_active == 1)
            flags |= __WQ_ORDERED;
对于最大worker为1且没绑定具体cpu的workqueue,系统也是默认整个workqueue是有序执行的。
 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1276049.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

助力android面试2024【面试题合集】

转眼间&#xff0c;2023年快过完了。今年作为口罩开放的第一年大家的日子都过的十分艰难&#xff0c;那么想必找工作也不好找&#xff0c;在我们android开发这一行业非常的卷&#xff0c;在各行各业中尤为突出。android虽然不好过&#xff0c;但不能不吃饭吧。卷归卷但是还得干…

什么是美颜SDK?市面常用直播美颜SDK的技术比较

直播平台美颜技术其中的核心就是美颜SDK。本文将深入探讨什么是美颜SDK&#xff0c;以及市面上常用的直播美颜SDK的技术比较。 一、美颜SDK简介 美颜SDK&#xff0c;使开发者能够在其应用或平台中集成美颜特效。对于直播平台而言&#xff0c;美颜SDK的引入旨在提供实时、高质…

LabVIEW在调用image.cpp或drawmgr.cpp因为DAbort而崩溃

LabVIEW在调用image.cpp或drawmgr.cpp因为DAbort而崩溃 出现下列问题&#xff0c;如何解决&#xff1f; 1. LabVIEW 程序因image.cpp或drawmgr.cpp中的错误而崩溃 2. 正在通过cRIO-9034运行独立的LabVIEW应用程序&#xff0c;但它因drawmgr.cpp中的错误而崩溃 …

利用reddit的api进行爬虫

1 介绍 Reddit是一个社交新闻聚合网站&#xff0c;用户可以发布、评价和讨论各种话题。Reddit的内容涵盖了广泛的主题&#xff0c;可以从中获取大量的文本数据进行情绪分析。 2 注册 2.1 注册reddit 你需要先注册一个reddit的账号。 2.2 注册api https://www.reddit.com/…

微服务架构:解析分布式系统的演进

目录 微服务是什么&#xff1f; 微服务的优势 微服务的挑战 应对微服务挑战的方法 结论 在当今快速发展的软件开发领域&#xff0c;微服务架构成为一种备受瞩目的设计理念&#xff0c;被广泛应用于构建灵活、可扩展的分布式系统。本文将深入探讨什么是微服务&#xff0c;为…

LeetCode困难题(分发糖果--接雨水)

分发糖果 n 个孩子站成一排。给你一个整数数组 ratings 表示每个孩子的评分。 你需要按照以下要求&#xff0c;给这些孩子分发糖果&#xff1a; 每个孩子至少分配到 1 个糖果。相邻两个孩子评分更高的孩子会获得更多的糖果。 请你给每个孩子分发糖果&#xff0c;计算并返回…

线性回归既是一种数据挖掘与建模算法,也是统计学领域、计量经济学领域的常用学术建模方法,有何不同?

一.线性回归的基本形式 线性回归既是一种数据挖掘与建模算法&#xff0c;也是统计学领域、计量经济学领域的常用学术建模方法。在数据挖掘与建模领域&#xff0c;线性回归算法是一种较为基础的机器学习算法&#xff0c;其基本思想是将响应变量&#xff08;因变量、被解释变量&…

MySQL安全相关——TDE和数据脱敏功能介绍

MySQL作为一款广泛使用的开源关系型数据库管理系统(RDBMS)&#xff0c;其安全性一直是开发者和企业关注的重点。在MySQL中&#xff0c;有一些与安全相关的功能&#xff0c;其中包括Transparent Data Encryption(TDE)和数据脱敏。本文将对这些功能进行介绍。 一、Transparent Da…

使用 kubeadm 部署 Kubernetes 集群(二)k8s环境安装

一、安装containerd 安装 k8s 有几种方式&#xff1a; 1、 Kubeadm 2、 二进制 这两个是 k8s 官网提供的方式&#xff0c;也是生产环境用的还可以借助第三方平&#xff1a;rancher、kubesphere 都可以装 k8s 这里使用 kubeadm 1.安装 containerd 在 Kubernetes 集群中&#…

CSS——基础选择器、文字控制属性

1、CSS定义 层叠样式表&#xff08;Cascading Style Sheets&#xff0c;缩写为CSS&#xff09;&#xff0c;是一种 样式表 语言&#xff0c;用来描述 HTML 文档的呈现&#xff08;美化内容&#xff09;。 书写位置&#xff1a;title 标签下方添加style双标签&#xff0c;styl…

externalTrafficPolicy 再探

一 externalTrafficPolicy 属性再探 一次网络不通"争吵"引发的思考 K8s中的external-traffic-policy是什么? 说明&#xff1a; 阿里云的 EDAS 和ACK的默认行为不一样 Kubernetes(二十三)Service(二)会话保持和获取客户端的ip 访问 externalTrafficPolicy 为 L…

二分查找与搜索树高频问题

关卡名 逢试必考的二分查找 我会了✔️ 内容 1.山脉数组的峰顶索引 ✔️ 2.旋转数字的最小数字 ✔️ 3.寻找缺失数字 ✔️ 4.优化求平方根 ✔️ 5.中序与搜索树原理 ✔️ 6.二叉搜索树中搜索特定值 ✔️ 7.验证二叉搜索树 ✔️ 基于二分查找思想&#xff0c;可以拓展出很…

IntelliJ IDEA 之初体验(上)

IntelliJ IDEA 是一款由 JetBrains 公司开发的强大的集成开发环境&#xff08;IDE&#xff09;&#xff0c;专注于 Java 开发&#xff0c;同时支持多种其他编程语言。本文将详细介绍 IntelliJ IDEA 的安装过程以及一些常用的基本操作。 第一步&#xff1a;下载与安装 IntelliJ…

LeetCode Hot100 75.颜色分类

题目&#xff1a; 给定一个包含红色、白色和蓝色、共 n 个元素的数组 nums &#xff0c;原地对它们进行排序&#xff0c;使得相同颜色的元素相邻&#xff0c;并按照红色、白色、蓝色顺序排列。 我们使用整数 0、 1 和 2 分别表示红色、白色和蓝色。 必须在不使用库内置的 so…

LeetCode 2661. 找出叠涂元素:多次映射

【LetMeFly】2661.找出叠涂元素&#xff1a;多次映射 力扣题目链接&#xff1a;https://leetcode.cn/problems/first-completely-painted-row-or-column/ 给你一个下标从 0 开始的整数数组 arr 和一个 m x n 的整数 矩阵 mat 。arr 和 mat 都包含范围 [1&#xff0c;m * n] 内…

UPDF 已集成 ChatGPT,AI 赋能注入新动能!

ChatGPT 掀起全球AI热潮,引发了世界范围内对AIGC未来会如何重塑各行各业的讨论与畅想。近日,由赛博爱思(上海)软件科技有限公司独立自主研发的国产 PDF 软件 UPDF完成版本更新,正式上线 AI 功能。据悉,UPDF AI完美集成了ChatGPT 的技术,可帮助用户智能阅读、总结、翻译、问答PD…

实现一个简单的网络通信上

那么我们的服务器有了&#xff0c;接下来就是初始化服务器 我们写的是基于udp协议的服务器&#xff0c;如果你想进行网络编程&#xff0c;那么创建的第一个就是socket 创建套接字 domain参数 所以当我们创建一个套接字时&#xff0c;你得说明未来使用这些套接字对应的类型是什…

19、串口向电脑发送数据电脑通过串口控制LED

串口向电脑发送数据 main.c #include <REGX52.H> #include "Delay.h" #include "UART.h"unsigned char Sec;void main() {//串口初始化UART_Init(); while(1){//串口发送1个字节UART_SendByte(Sec); Sec; Delay(1000); } }UART.c #include &…

学习笔记8——JUC入门基础知识

学习笔记系列开头惯例发布一些寻亲消息 链接&#xff1a;https://baobeihuijia.com/bbhj/contents/3/199561.html 进程和线程:进程是资源分配的最小单位&#xff0c;线程是CPU调度的最小单位 进程和线程的主要区别&#xff08;总结&#xff09;_进程和线程的区别-CSDN博客进程…