linux 内核工作队列技术原理

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

  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是有序执行的。
 

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

MIAOYUN荣获“2023中国赛宝信息技术应用创新优秀解决方案应用创新示范方向三等奖”

11月30日&#xff0c;2023&#xff08;第四届&#xff09;数字化转型推动高质量发展大会在中国海口成功召开&#xff0c;会上举办了2023中国赛宝信息技术应用创新优秀解决方案征集活动颁奖仪式。成都元来云志科技有限公司&#xff08;简称“MIAOYUN”&#xff09;联合国网浙江省…

15、 深度学习之正向传播和反向传播

上一节介绍了训练和推理的概念,这一节接着训练和推理的概念讲一下,神经网络的正向传播和反向传播。 其实单看正向传播和反向传播这两个概念,很好理解。 正向传播(Forward Propagation)是指从输入层到输出层的数据流动过程,而反向传播(Backpropagation)是指数据从输出…

element ui el-date-picker日期时间选择器 设置只能选择不大于30天时间范围

需求&#xff1a;要求日期时间选择器只能选择最多32天&#xff0c;其他日期为不可点击状态。 日期组件type为daterange或者datetimerange都生效 实现&#xff08;vue2.x&#xff09;&#xff1a; 通过属性picker-options html <el-date-pickerv-model"dateTime&qu…

<Linux>(极简关键、省时省力)《Linux操作系统原理分析之存储管理(2)》(15)

[TOC](《Linux操作系统原理分析之存储管理&#xff08;2&#xff09;》&#xff08;15&#xff09; 5 存储管理5.4 分页存储管理5.4.1 纯分页存储管理a.页&#xff08;页面&#xff09;和物理块&#xff08;帧&#xff09;b. 页面大小c. 逻辑地址结构 5.5 存储扩充技术5.5.2 交…

spring cache 学习 —— @Cacheable 使用详解

1. 功能说明 Cacheable 注解在方法上&#xff0c;表示该方法的返回结果是可以缓存的。也就是说&#xff0c;该方法的返回结果会放在缓存中&#xff0c;以便于以后使用相同的参数调用该方法时&#xff0c;会返回缓存中的值&#xff0c;而不会实际执行该方法。 注意&#xff0c;这…

上门预约洗鞋店小程序

互联网洗鞋店小程序开发&#xff0c;结合洗鞋行业线下实际运营情况和经验&#xff0c;专为洗鞋人、洗鞋店打造的高效、实用、有价值的洗鞋私域流量管理软件系统。 帮助洗鞋人建立自己的私域流量&#xff0c;实现会员用户管理&#xff0c;用户与商家点对点互联互通&#xff0c;提…

okhttp导致的内存溢出(OOM)sun.security.ssl.SSLSocketImpl

使用分析工具&#xff1a;MAT(Memory Analyzer Tool)、JvisualVM占用内存&#xff1a;sun.security.ssl.SSLSocketImpl 一、 项目场景&#xff1a; 功能&#xff1a;一个定时任务(xxl-job)采用线程池的方式多线程请求第三方拉取数据&#xff0c;网络框架使用okhttp3。 问题&am…

从零开发短视频电商 在AWS上用SageMaker部署开源模型并用Java SDK调用

文章目录 1.创建AWS账户2.登录AWS3.创建域4.部署模型方式一 使用JumpStart可视化界面部署内置的模型方式二 采用python脚本部署私有模型5.调用模型AWS Java SDK调用Http调用6.监控7.自动扩缩容1.创建AWS账户 需要准备好邮箱一个,支持visa功能的信用卡一个。然后到aws上自己去…

手动部署1个Cloud Run service

什么是Cloud Run 来自chatgpt&#xff1a; Google Cloud Run 是一项全托管的服务器托管平台&#xff0c;它允许您在容器化的环境中运行无服务器应用程序。Cloud Run 提供了一种简单而灵活的方式来构建、部署和扩展应用程序&#xff0c;无需管理底层基础设施。 以下是 Cloud …

Linux-Linux安装JDK及配置环境 及 遇到的问题

下载linux环境对应的JDK的tar.gz包 配置JDK环境&#xff1a;编辑 sudo vim /etc/profile 在文件的最下方&#xff0c;填写 export JAVA_HOME/usr/local/src/software/jdk1.8 export CLASSPATH.:$JAVA_HOME/lib/tools.jar export PATH$JAVA_HOME/bin:$PATH 执行生效命令&…

2024年甘肃省职业院校技能大赛中职组 电子与信息类“网络安全”赛项竞赛样题-B卷

2024 年甘肃省职业院校技能大赛中职组 电子与信息类“网络安全”赛项竞赛样题-B卷 2024 年甘肃省职业院校技能大赛中职组 电子与信息类“网络安全”赛项竞赛样题-B卷A 模块基础设施设置/安全加固&#xff08;200 分&#xff09;A-1&#xff1a;登录安全加固&#xff08;Windows…

电商店铺搬家API接口,轻松搬运淘宝1688京东拼多多等平台全站商品丨商品详情业数据接口丨搜索商品列表数据接口

轻松搬运淘宝、1688、京东、拼多多等平台全站商品的API接口通常是由各平台提供的官方开发工具或第三方工具提供的。 对于淘宝和1688平台&#xff0c;可以使用淘宝开放平台&#xff08;Open Platform&#xff09;提供的API接口来访问和操作商品信息。淘宝开放平台提供了丰富的A…

基于通义千问和向量数据构建问答知识库

参考&#xff1a;Java从0到1构建基于ChatGPT向量数据库的检索增强生成模型RAG-02 - 知乎 (zhihu.com) 1、先开通 阿里云的向量检索服务 如何开通向量检索服务并创建API-KEY_向量检索服务-阿里云帮助中心 (aliyun.com) 按流程申请 最后需要申请API-KEY 安装DashVector SDK M…

Windows的常用cmd命令总结

文章目录 一.盘符切换二: cd命令(打开文件/文件夹)三:查看目录四.创建和删除文件夹五.查看本机ip地址六.清除当前屏幕七.复制文件到另一个地方八.移动文件到另一个地方九.删除文件&#xff08;不能删除文件夹&#xff09;十.测试网络连接十一.停止任务进程Windows快捷键总结大全…

Linux 文件管理

内容概述 1 文件系统目录结构 存放的是内存中正在运行的系统状态信息&#xff0c;数据不在硬盘而是在内存中 echo 1 > /proc/sys/net/ipv4/icmp_echo_ignore_all1.1 文件系统的目录结构 Linux 操作系统 ext / xfs 文件系统是区分大小写&#xff0c;大小写敏感 Linux的文件…

RPG项目01_场景及人物动画管理器

基于“RPG项目01_UI登录”&#xff0c;新建一个文件夹名为Model&#xff08;模型&#xff09; 将资源场景拖拽至Model中 找到相应场景双击进入 红色报错部分Clear清掉即可&#xff0c;我们可以重做 接下来另存场景 起名为Game 点击保存 场景就保存至Scene中了 在文件夹下新创建…

SpringBoot Bean解析

Bean解析 IOC介绍 松耦合灵活性可维护 注解方式配置Bean 实现方式1: Component声明,直接类上进行添加注解, 同时保证包扫描能扫到即可实现方式2: 配置类中使用Bean Configuration public class BeanConfiguration implements SuperConfiguration{Bean("dog")Ani…

探索云原生时代:技术驱动的业务架构革新

一、引言 在数字化浪潮中&#xff0c;云原生技术已成为推动企业快速创新的重要动力。本文将深入探讨云原生的核心理念、技术架构以及其在实际业务环境中的应用&#xff0c;带领读者深入理解云原生技术的复杂性和优势。 云原生技术的定义 云原生&#xff08;Cloud Native&…

HarmonyOS脚手架:UI组件之文本和图片

前言 关于HarmonyOS脚手架&#xff0c;本篇是系列的第二篇&#xff0c;主要实现UI组件文本和图片的常见效果查看&#xff0c;本身功能特别的简单&#xff0c;其目的也是很明确&#xff0c;方便大家根据效果查看相关代码实现&#xff0c;可以很方便的进行复制使用&#xff0c;当…

cmake和vscode 下的cmake的使用详解(二)

第四讲&#xff1a; GDB 调试器 前言&#xff1a; GDB(GNU Debugger) 是一个用来 调试 C/C 程序 的功能强大的 调试器 &#xff0c;是 Linux 系统开发 C/C 最常用的调试器 程序员可以 使用 GDB 来跟踪程序中的错误 &#xff0c;从而减少程序员的工作量。 Linux 开发 C/C …