Linux学习第26节,内核发现工作太多时,会让它们排队等待处理官网介绍
如第24节所述,为了解决处理中断时“想更快地完成任务”的矛盾,Linux内核将一个完整的中断处理分为“上半部分”和“下半部分”,所有需要更多时间但不需要高实时性能的处理都放在下半部分。
2.6.26版本Linux内核有三种形式的“下半部分”:软中断、小任务和工作队列。前两节主要讨论软中断和微线程。我们已经知道软中断是在中断的上下文中,所以软中断处理程序不能阻塞。
无法休眠,这限制了软中断处理程序。tasklet也是如此,因为它是基于软中断机制实现的。
Linux内核中的工作队列。如果您想将工作的后半部分推迟到流程上下文,或者如果被推迟的任务需要休眠,则需要使用工作队列机制。Linux内核将把工作队列中的工作交给内核线程执行。
内核线程在进程上下文中运行,因此允许重新调度工作队列并允许其休眠。
工作队列子系统实际上是一组接口,通过它创建的进程(所谓的工作线程)负责执行Linux内核或其他模块分配给工作队列的任务。Linux内核提供了一个默认的工作线程(事件/n,
n是处理器号)来处理队列中的任务。这样,工作队列就变成了一组接口,将延迟的任务(排队的任务)移交给特定的线程(默认工作线程)。
Linux内核中工作队列使用的数据结构是workqueue_struct结构,其C语言代码如下。请看:
struct work queue _ struct { struct CPU _ work queue _ struct * CPU _ wq;struct list _ head list const char * namint singlethread不可冻结;/*挂起期间冻结线程*/# ifdef CONFIG _ lock dep struct lock dep _ map lock dep _ map;# endif };容易看出,
struct CPU _ work queue _ struct { spin lock _ t lock;结构列表_头工作列表;wait _ queue _ head _ t more _ work struct work _ struct * current _ work struct work queue _ struct * wqstruct task _ struct *线程;int run _ depth/*检测run_workqueue()递归深度*/} _ _ _ _缓存行对齐;显然,
处理工作队列中任务结构cpu_workqueue_struct的成员current_work表示工作线程要处理的工作,其数据结构由结构work_struct定义。C语言代码如下。
请看:
struct work _ struct { atomic _ long _ t data;结构列表_头条目;工作功能函数;};成员功能指向处理函数,
数据是它的参数。这些结构连接成一个链表,每个处理器上的每种类型的队列都对应于这样一个链表。例如,上面提到的“默认工作线程”就有这样一个链表。
当工作线程被唤醒时,它将执行链表中的所有工作。执行后,相应的work_struct将从链表中移除。当列表为空时,工作线程再次进入睡眠状态。
这个过程由worker_thread()函数完成,其C语言代码如下。请看:
299静态int worker _ thread(void * _ _ cwq )- 300 {.|- 309为(;){ | | 310 prepare _ to _ wait(cwq-more _ work,wait,TASK _ INTERRUPTIBLE);|| 311 if(!冻结(当前)|| 312!kthread _ should _ stop()| | 313 list _ empty(cwq-worklist))| | 314 schedule();|| 315完成_等待(cwq-更多_工作,等待);| | 316 | | 317 try _ to _ freeze();| | 318 | | 319 if(kthread _ should _ stop())| | 320 break;| | 321 | | 322 run _ work队列(cwq);| | 323 } | 324 | 325 return 0;| 326 }请看黄框中的核心代码,
run_workqueue()函数的C语言代码很长,但逻辑并不复杂。它只不过是从链表中取出节点对象并逐个执行它们,因此我在此不再赘述。好了,既然您已经了解了Linux内核如何设计和实现工作队列,
让我们看看如何使用它。
使用工作队列的Linux内核,定义了DECLARE_WORK宏来静态创建work_struct结构。它的C语言代码如下。请看:
# define DECLARE _ WORK(n,f)\ struct WORK _ struct n=_ _ WORK _ INITIALIZER(n,f)# define _ _ WORK _ INITIALIZER(n,f){ \。data=WORK_DATA_INIT()。条目={(n)。条目。条目},\。func=(f),\ _ _ WORK _ INIT _ lock dep _ MAP(# n,(n))\ }其实就是创建一个工作结构结构体并赋值。
# define INIT _ WORK(_ WORK,_ func)\ do { \(_ WORK)-DATA=(atomic _ long _ t)WORK _ DATA _ INIT();\ INIT _ LIST _ HEAD((_ work)-entry);\ PREPARE _ WORK((_ WORK),(_ func));\ } while(0)再来看看工作队列的处理函数,
void work _ handler(void * data);该函数由工作线程执行,因此它在进程上下文中运行,允许响应被中断,并且可以休眠和被调度。创建作业后,
它可以通过schedule_work()函数移交给默认的工作线程。它的C语言代码如下。请看:
int schedule _ work(struct work _ struct * work){ return queue _ work(keventd _ wq,work);}容易看出,
schedule_work()的函数实际上将工作添加到全局工作队列keventd_wq中,这是由queue_work()的函数完成的。其C语言代码如下:
int queue _ work(struct work queue _ struct * wq,struct work _ struct * work){ int ret=0;如果(!test _ and _ set _ bit(WORK _ STRUCT _ PENDING,WORK _ data _ bits(WORK)){ BUG _ ON(!list _ empty(工作条目);_ _ queue _ work(wq _ per _ CPU(wq,get_cpu(),work);put _ CPU();ret=1;浸水使柔软返回;}容易看出,
我在这里理解schedule_work()函数的核心是将工作添加到工作队列中并排队等待执行。
当然,Linux内核也允许创建新的工作线程,但不建议这样做,因此相关分析留给读者自己去做。至此,我们大致分析了Linux内核中的三种中断类型。“软中断”适用于处理实时要求,
需要经常执行的工作,但有必要确保共享数据的同步安全性。Tasklet可以确保同一类型的工作不会同时在多个处理器上运行,但它是基于“软中断”的,因此它在中断上下文中与“软中断”一样。
没有睡眠,没有堵塞。如果延迟的工作需要在流程上下文中运行,您应该选择工作队列。
欢迎在评论区一起讨论和提问。文章均为手工原创(本文部分涉及linux内核的原理与设计)。每天以最简单的方式介绍C语言、linux等嵌入式开发。如果你喜欢我的文章,关注一波,你可以看到最新的更新和以前的文章。
版权声明
1、本文内容转载自Linux学习第26节,内核发现工作太多时,会让它们排队等待处理(),或有会员发布,版权归原网站/法人所有。
2、本站仅提供信息发布平台,不承担相关法律责任。
3、文章仅代表作者个人观点,不代表本站立场,未经作者许可,不得转载。
4、若侵犯您的版权或隐私,请联系本站管理员删除。
口碑点评
警告:请理性点评、打分,请文明用语!请给“Linux学习第26节,内核发现工作太多时,会让它们排队等待处理”打分并给出您的宝贵点评意见
Linux学习第26节,内核发现工作太多时,会让它们排队等待处理收录查询
Linux学习第26节,内核发现工作太多时,会让它们排队等待处理SEO综合查询
-
搜索引擎百度PC百度移动头条搜狗360pPC360移动神马
-
权重
-
关键词
-
IP来路
推荐网站
-
一次消息队列堆积问题排查,我把坑踩了个遍!
一、背景本次问题涉及的系统链路如上图,各系统的基本职责为:Proxy:提供请求代理服务。统一代理发往下游系统的各类请求,从而让上游系统无需感知下游各服务的使用差异;同时提供精细化的限流、导流等服务特性;拉图 SDK:面向各存储平台提供统一的
更新时间:2024-01-26 03:26:26 -
第五人格:为何监管者玩家越来越多?网友:享受抓人的快感!
在第五人格手游中,不知小伙伴们是否发现,每当你选择监管者并开始案件还原时,总会出现“您当前选择的阵营队列人数过多”的提示,不得不说,监管者玩家的数量已经变得越来越多,下面小编就来分析一下屠夫玩家变多的原因?一起来看看吧!原因一:享受抓人的快
更新时间:2024-01-26 03:26:26 -
实战总结|记一次消息队列堆积的问题排查
吉多 阿里开发者 2023-07-18 09:01 发表于浙江阿里妹导读本文记录了一次问题的排查过程,从中可以学到不少共性的方法论和经验教训,所以做了提炼归纳。(文末有活动)一、背景本次问题涉及的系统链路如上图,各系统的基本职责为:Prox
更新时间:2024-01-26 03:26:26 -
大数据面试-Kafka 小结
技术是需要自己去沉淀的,沉淀的过程就是在与不断的学习和理解。加油,奥里给Kafka 的相关总结Kafka 架构我们直接看个图:Kafka 压测Kafka 官方自带压力测试脚本(kafka-consumer-perf-test.sh、kafk
更新时间:2024-01-26 03:26:26 -
暗黑破坏神4暗黑4 PS、Xbox主机提示登录列队位置验证中解决办法
暗黑破坏神4是全新大作,好消息是暗黑破坏神4的beta公测抢先试玩和正式开测都按期到来,玩家们可以根据自己的情况试玩或参与公测。部分玩家反馈暗黑破坏神4暗黑4 PS、Xbox主机提示登录列队位置验证中,无法正常进入游戏,为此小编带来暗黑破坏
更新时间:2024-01-26 03:26:26 -
Java项目:并发队列中的任务堆积导致队列溢出
当Java项目中的并发队列中的任务堆积过多时,可能会导致队列溢出,引发一系列问题。下面将详细解释这个问题,并提供一些解决方案。首先,让我们了解一下什么是并发队列。并发队列是在多线程环境下使用的数据结构,它可以安全地处理并发访问和操作。常见的
更新时间:2024-01-26 03:26:26 -
消息队列堆积太多,下游处理不过来怎么办呢?
原文链接:https://mp.weixin.qq.com/s/BhhiUrQECX-KS57rRbrRzQ作为后端程序员日常工作中难免会遇到要跟消息队列打交道的时候,而且在当下微服务的场景下,很多服务的性能不是我们自己能控制的。这不阿粉最
更新时间:2024-01-26 03:26:26 -
数仓/数开面试题真题总结(四)
四.Kafka1.Kafka名词解释和工作方式Producer :消息生产者,就是向kafka broker发消息的客户端。Consumer :消息消费者,向kafka broker取消息的客户端Topic :咱们可以理解为一个队列。Con
更新时间:2024-01-26 03:26:26 -
阴阳师万事屋怎么升级快?阴阳师万事屋快速升级攻略技巧
阴阳师万事屋怎么升级快呢 下面小编为大家带来阴阳师万事屋快速升级攻略,快一起来看看吧。阴阳师万事屋快速升级攻略一句话总结:白天主要卖产品,保持风水玉接近上限,消耗全部火玉;睡觉时主要制作风水产品,火玉自然恢复,只用挂两个委派雷2水2;雷三级
更新时间:2024-01-26 03:26:26 -
消息队列大量积压怎么办?,消息队列积压了大量消息怎么处理
Q:刚开始是对这个疑问抱有质疑态度的,因为使用消息队列的其中目的就是削峰填谷,来避免高流量时,对下游服务的冲击,所以使用消息队列进行缓冲,下游根据自己的消费能力去消费,我感觉这就是消息积压本就是使用消息队列的功能,怎么会是问题呢?A:首先
更新时间:2024-01-26 03:26:26