并发管理工作队列(kernel译文[1])

Linux内核工作队列workqueue详解 linux 内核 workqueue详解 阅读详情

并发管理工作队列(Concurrency Managed Workqueue)

9月,2010

目录
介绍
为什么是cmwq?
设计
API
运行情景举例
指南
调试

介绍

       异步进程的执行在很多情况下会发生,而workqueue的API就是针对这些情况最经常使用的机制。
当需要异步执行时,会将一个描述哪个函数将要执行的工作项(workitem)放入一个队列(queue)当中。一个独立的线程会作为异步可执行的上下文。该队列被称为工作队列(workqueue),该线程则被称为工作者(worker)
当在工作队列(workqueue)中有很多工作项(workitem)时,工作者(worker)会一个个的执行与工作项相关联的函数。

为什么是cmwq?

       在原始的wq的实现中,多线程(MT)的wq每一个cpu都会有一个工作者线程,而单线程(ST)的wq在整个系统中只有一个工作者线程。一个多线程wq需要维系和CPU数量等同的工作者数。内核这几年增加了很多MT wq的使用者,并且随着cpu核的数量的不断增加,一些系统在刚启动后默认的32K的pid空间就已经饱和了。

       虽然MT wq浪费了很多的资源,但是所提供的并发的级别仍然没有得到满足。尽管单线程wq的这种情况没有多线程wq严重,但是这种限制在两者上都是普遍发生的。每一个wq都会维护其自己独立的工作者线程池。MT wq会为每一个cpu提供一个可执行上下文(就是worker thread),而ST wq则是在整个系统中维护一个可执行上下文。多个工作项不得不为了那些有限制的可执行上文来进行竞争,而这种竞争则导致了各种各样的问题,这些问题包括在单个可执行上下文中极易造成死锁的问题。

       并发水平和资源使用的矛盾造成的担忧致使它们的使用者做了很多不必要的权衡工作。譬如libata选择使用ST wq来polling PIOs,同时意味着其接受了在同一时间没有两个polling PIOs同时进行的事实。因为MT wq并不能提供更好的并发,那么需要更高并发水平的用户(如async,fscache)不得不实现他们自己的线程池。

       而cmwq则是对之前wq的一种重新实现,而这种实现则主要为了实现下面这些目标:
* 保持和之前的工作队列API的兼容
* 所有的wq使用基于per-CPU的统一的工作者线程池,从而提供更灵活的按需的并发水平,并且不会浪费很多资源
* 自动调节工作者线程池和并发水平之间的矛盾,不需要用户担心太多的其中的细节

设计

       ​为了减轻函数异步执行的压力,推出了一个新的抽象概念“工作项(work item)”。

       工作项只是一个简单的struct结构,这个结构包含了一个指向将要异步执行的函数指针。无论什么时候,当一个驱动或是子系统模块想要异步执行一个函数,那么这个模块必须要建立这样的一个结构,然后将该函数指针指向将要执行的函数,并将work item放入工作队列中。

       一些被称为工作者线程(worker thread)的特殊线程,他们会从工作队列中将工作项一个个的取出来执行。如果队列空了,那么该线程就会进入idle状态。这些工作者线程被统一管理起来,就是所谓的工作者线程池(worker-pools)。

       cmwq的设计思想中,做了两部分区分,分别是面向用户的前端设计,包括驱动程序或子系统如何放入和取出工作项的接口;以及管理工作者线程并处理工作者项的后端机制。
在每个可能的CPU上,有两个工作者线程池,一个是为普通的工作项准备的,另一个是为高优先级的工作项准备的,还有一些额外的工作者线程池,这些线程池是为那些放入unbound队列的工作项准备的。这些后台线程池的数量是动态变化的。

       子系统模块可以通过 API函数接口来创建工作项,并将其放入相应队列中。它们还可以通过对工作队列设置一些标记来影响在其上执行的工作项的行为方式。这些标记包括如cpu locality,并发限制(concurrency limits),优先级等。想要获取更多的细节,请参考对下面alloc_workqueue()函数接口的描述。

       当工作项被放入工作队列的时候,目标工作者线程池就已经被确定了并且被添加到共享的worklist中。确定条件就是放入队列参数,队列属性。譬如,除非被覆盖,否则一个bound队列中的工作项会被添加到对应的队列中,而相应的线程池要么是normal,要么是highpri的线程池,并且相应的cpu也是该工作项运行的那个cpu。

       对于任何一种工作者线程的实现来说,如何管理好并发水平(就是多少可执行上下文是激活状态)都是一件非常重要的事情。cmwq试图保持最小的并发状态,并且在这种状态下对于系统来说还能够实现最大的工作效率。

       每一个绑定到CPU上的线程池实现并发管理都是和进程调用器(scheduler)挂钩的。当一个工作者线程被唤醒,或是进入睡眠状态的时候,该工作者线程池就会被通知到,而且该线程池会跟踪当前可以运行的工作者线程的数量。一般的,工作项不应该独占CPU并消耗许多cpu时间周期。这就意味着如何维持足够的并发而又能防止工作项的运行有延迟是需要被调优的。只要在一个cpu上有一个或多个可运行的工作者,那么线程池就不会再启动新的工作,但是,当最后一个运行的工作者进入休眠状态后,系统会立刻调度一个新的工作者使得该CPU不会因为闲置而阻塞工作项。这样的话就能够既使用了最小数量的工作者,又不会损失执行带宽。

       对于kthreads来说,使工作者线程处于idle状态并不会消耗更多除内存外的其他资源,所以cmwq会在杀死这些线程之前使他们保持一段idle状态。

       对于unbound的工作队列,后台的线程池的数量是动态的。unbound的工作队列可以使用apply_workqueue_attrs()接口函数自定义属性,并且该队列会自动的创建符合该属性的后台工作者线程池。调节并发的责任在使用者。对于bound wq来说,也有一个flag来标记让其忽略并发管理。更多细节请参考API部分。

       当更多的可执行上下文是必要的时候,工作者线程可以被创建,这个机制是进程能够进行下去的保障。反过来说,我们可以通过救援工作者线程(rescue worker)来确保进程的顺利执行。举个例子,当所有的需要处理内存回收的工作项都被放到队列中时,就需要有一个救援工作者在内存压力大的情况下执行这些工作项。否则,就可能会造成线程池的死锁,因为它正在等执行上下文去释放内存。

应用程序接口(API)

       alloc_workqueue()分配一个工作队列。原先的create_*workqueue()函数已经过时了,并且以后会在kernel中被移除。alloc_workqueue()需要三个参数 —— @name,@flag和@max_active。@name是wq的名称,并且会被当做相应救援线程的名称。

       工作队列已经不再对执行资源进行管理了,但是它作为域保证了进程的运行,flush,以及工作项的属性。@flag和@max_active用来控制到底有多少工作项被分配了执行资源,被调度和执行。

@flag:

WQ_UNBOUND
    unbound队列中的工作项会被相应的工作者线程池处理,这些线程池管理的工作者
不会和任何制定的CPU绑定。这样的话,该队列的行为就相当于是提供了一个简单的执行
上下文,而不会做并发管理。未绑定的线程池只要有可能就会试图启动工作项的执行。未
绑定的队列牺牲了cpu的相关性,但是有一下用处。

* 我们期盼并发需求的宽度浮动,并且如果使用bound的队列会因为在不同的cpu上运行
  导致在多个cpu上产生很多不用的工作者线程。

* 长时间运行的CPU负载能够更好的被系统调度程序管理。 

WQ_FREEZABLE

冻结队列因为参与了系统的挂起操作流程,在该队列上的工作项会被排出(**drained**),直到被解冻之前都不会有新的工作项被执行。

WQ_MEM_RECLAIM

所有有可能运行在内存回收流程中的工作队列都需要设置该标记。这样能够确保不管是否在内存压力比较大的情况下都能有至少一个执行上下文能够运行。

WQ_HIGHPRI

highpri的队列中的工作项会被被指定的cpu上的工作者线程池来处理。highpri工作者线程池中的线程具有较高的nice level。

注意,normal和highpri工作者线程池不会相互之间进行交互。每一个只是单独的维护去自己池中的工作者,并且对其进行并发管理工作。

WQ_CPU_INTENSIVE

CPU密集型工作队列中的工作项并不会对并发级别产生贡献。换句话说,可以运行的CPU密集型工作项不会阻止相同工作者线程池上的工作项的运行。对于绑定的并且希望独占CPU周期的工作项,这个flag是有用的,因为它们的运行可以被系统进程调度程序调节。

虽然CPU密集型的工作项不对并发级别做出贡献,但是它们的执行仍然会被并发管理所调节,因为可以运行的那些非CPU密集型工作项可以延迟CPU密集型工作项的运行。

这个标记对于unbound工作队列没有什么意义。

    注意,标记WQ_NON_REENTRANT不再存在了,因为当前所有的工作队列都是non-reentrant的 - 任何工作项从系统的角度来说,在任何时候最多只会由一个工作者运行。

@max_active:

       @max_active决定了分配到工作队列的工作项的每个CPU上的执行上下文的最大数量。例如,如果@max_active是16,那么同一个CPU上同一时刻最大只有16工作项可以工作。

       目前,对于bound工作队列,@max_active的最大限制值是512,并且默认的值为0的时候表示为256。 对于unbound工作队列,这两个的限制(maximum limit & default value)分别是512和4* num_possible_cpus()。之所以会选择一个这么高的值,是为了在系统在失控的时候提供保护的情况下,它们不会成为关键的限制因素。

       一个队列中的激活状态的工作项的数量一般来说是由队列的用户来进行调节的,更具体的说,是用户在同一时刻能够将多少工作项放入队列的数量是有用户自己决定的。除非一些特殊的要求需要限制工作项的数量,一般推荐默认的‘0’。

       一些用户需要依赖ST wq的严格的顺序执行的特点。那么将@max_active设置成1并且将flag设置成WQ_UNBOUND被用来实现这个行为。在这中wq上的工作项总是会被放入unbound的工作者线程池,并且在任意时刻都只有一个工作项被激活。这样就能够实现类似ST wq的相同顺序执行的特性。

一些执行的场景

       下面的一些执行场景用来说明cmwq在不同的配置下的行为。

       工作项w0,w1,w2被放入同一个CPU上的一个bound队列中。w0消耗了CPU 5ms的时间然后进入休眠10ms,然后再次消耗CPU 5ms。w1和w2消耗cpu 5ms然后进入休眠10ms。

       忽略所有的其他任务,工作和处理开销, 假设就只是简单的FIFO调度,那么下面的列表是一个高度简化的事件可能发生的顺序的版本。

TIME IN MSECSEVENT
0w0 starts and burns CPU
5w0 sleeps
15w0 wakes up and burns CPU
20w0 finishes
20w1 starts and burns CPU
25w1 sleeps
35w1 wakes up and finishes
35w2 starts and burns CPU
40w2 sleeps
50w2 wakes up and finishes

如果设置@max_active 大于等于3

TIME IN MSECSEVENT
0w0 starts and burns CPU
5w0 sleeps
5w1 starts and burns CPU
10w1 sleeps
10w2 starts and burns CPU
15w2 sleeps
15w0 wakes up and burns CPU
20w0 finishes
20w1 wakes up and finishes
25w2 wakes up and finishes

如果@max_active等于2

TIME IN MSECSEVENT
0w0 starts and burns CPU
5w0 sleeps
5w1 starts and burns CPU
10w1 sleeps
15w0 wakes up and burns CPU
20w0 finishes
20w1 wakes up and finishes
20w2 starts and burns CPU
25w2 sleeps
35w2 wakes up and finishes

现在我们假设w1和w2被放入了另一个队列q1中,并且该队列的WQ_CPU_INTENSIVE标记被设置。

TIME IN MSECSEVENT
0w0 starts and burns CPU
5w0 sleeps
5w1 and w2 start and burn CPU
10w1 sleeps
15w2 sleeps
15w0 wakes up and burns CPU
20w0 finishes
20w1 wakes up and finishes
25w2 wakes up and finishes

指南

  • 如果一个队列可能会处理进行内存回收的工作项,那么不要忘记使用WQ_MEM_RECLAIM标记。每一个带有WQ_MEM_RECAIM的队列都有一个保留的执行上下文。如果在内存回收的过程中,各个工作项之间有依赖关系,那么它们必须要被放入不同的队列中,而这些队列也要带有WQ_MEM_RECLAIM标记。

  • 除非是需要严格的顺序执行条件,否则不需要使用ST wq。

  • 除非有特殊需要,否则使用默认推荐的@max_active的值0。在一般的用户场景中,并发级别通常在该默认值下都能运行的很好。

  • 工作队列可以看做下面几个方面的域:进程运行的保障,WQ_MEM_RECLEAIM,flush以及工作项的属性。当一个工作项不需要进行内存回收,不需要作为一组工作项中的一部分被flush,不需要特殊的属性的时候,就可以使用系统的wq。在执行特性上,使用一个特定的wq和使用一个系统wq并没有什么不同。

  • 对于wq的操作以及工作项的执行来说,随着locality level的日益增长,除非工作项要消耗大量的CPU时间,否则最好使用bound队列。

调试

因为工作项的执行函数是被通用的工作者线程执行,有一些小技巧可以对于队列用户的不当行为进行分辨。

工作者线程在进程列表中显示如下:

root 5671 0.0 0.0 0 0 ? S 12:07 0:00 [kworker/0:1]
root 5672 0.0 0.0 0 0 ? S 12:07 0:00 [kworker/1:2]
root 5673 0.0 0.0 0 0 ? S 12:12 0:00 [kworker/0:0]
root 5674 0.0 0.0 0 0 ? S 12:13 0:00 [kworker/1:0]

If kworkers are going crazy (using too much cpu), there are two types of possible problems:
如果kworkers线程“疯了”(使用了太多的CPU),那么有两种可能的问题:

1. 有什么东东在不断的快速的被调度
2. 其中一个工作项消耗了很多CPU周期时间

第一种可能可以使用如下的方法进行跟踪:

$ echo workqueue:workqueue_queue_work > /sys/kernel/debug/tracing/set_event
$ cat /sys/kernel/debug/tracing/trace_pipe > out.txt
(wait a few secs)
^C

如果有什么在不断循环的忙于工作项的进出队列,那么这个动作的log会充斥着output的log,而引起此问题的罪魁祸首可以通过工作项函数被确认出来

对于第二类问题,通过跟踪检查该工作者线程的堆栈是有可能查出问题的。

$ cat /proc/THE_OFFENDING_KWORKER/stack

该工作项的函数应该在该stack trace中是可见的。

手把手教你学pcie--msix中断机制内核函数(八):alloc_workqueue 函数 是 Linux 内核中用于创建自定义工作队列(workqueue)的函数。它允许开发者灵活地定义一个工作队列,用于管理和调度异步任务。的使用方法,开发者可以更好地实现异步任务调度,构建高效、稳定的内核代码。的深入解析,包括其功能、参数、实现机制以及使用场景。以下是一个完整的示例,展示如何使用。 阅读详情

相关推荐

手把手教你学PCIE--MSI-X 和工作队列设计模式介绍(一)

是一种用于调度和执行异步任务的机制。它们允许驱动程序或内核模块将耗时或需要阻塞的操作推迟到稍后由内核线程执行,从而避免在中断上下文中执行复杂操作。以下是对工作队列和工作任务机制的详细解析,包括其设计目标、内部实现、使用场景以及注意事项。这种设计模式广泛应用于现代设备驱动程序中,能够显著提高系统的性能和可靠性,同时保持代码的清晰性和可维护性。在 Linux 内核中,

MHD0815的博客 214

linux cmwq介绍

一.简介 在很多情况下,我们需要一个异步的执行上下文。比如对于linux中断而言,我们可以把紧急的任务放在中断服务函数中进行,而把不紧急的任务延后执行。延后执行的方式有很多,比如 tasklet和软中断。但是tasklet和软中断的缺点是,虽然是延后执行,但是其执行期间还是属于中断上下文,中断上下文最大的问题是不能执行可能导致睡眠的函数,比如kmalloc。针对这个问题,内核提供了工作队列(wq...

weixin_39059738的博客 1934

手把手教你学PCIE--Linux 内核工作队列机制(三):queue_work 详细解释继续编辑

目录alloc_workqueue 详细解释1. 函数原型参数说明返回值2. 使用场景3. 示例代码4. 关键点解析4.1. 自定义名称4.2. 标志位的作用4.3. 最大并发线程数4.4. 销毁工作队列5. 注意事项6. 总结 是 Linux 内核中用于创建自定义工作队列(workqueue)的函数。它允许开发者创建一个专门的工作队列,用于管理和调度异步任务。以下是对 的详细解释,包括其功能、参数、使用场景以及注意事项。 c深色版本 参数说明 :::: 通常用于以下场景:需要自定义行

MHD0815的博客 308

Linux中断管理 (3)workqueue工作队列

关键词: 工作队列的原理是把work(需要推迟执行的函数)交由一个内核线程来执行,它总是在进程上下文中执行。 工作队列的优点是利用进程上下文来执行中断下半部操作,因此工作队列允许重新调度和睡眠,是异步执行的进程上下文,它还能解决软中断和tasklet执行时间过长导致系统实时性下降等问题。 当驱动程序或者内核子系统在进程上下文中有异步执行的工作任务时,可以使用work item来描述工作...

有趣的人生 一半是山川湖海 一半是初心情怀 2138

电力市场小白必看:手把手教你用Matlab实现市场出清电价计算(附完整代码)

本文为电力市场初学者提供了使用Matlab计算市场出清电价的完整指南。通过Yalmip和Matpower工具包,详细讲解了从环境配置到模型构建、求解及结果分析的整个过程,帮助读者快速掌握节点电价计算的核心技术。

weixin_30379531的博客 73

C#菜鸟教程学习笔记

C#菜鸟教程学习笔记 C#简介 C# 是一种编程语言,它是由微软开发的。 C# 编程是基于 C 和 C++ 编程语言的,它与 Java 也非常相似。 C# 是 .Net 框架的一部分,且用于编写 .Net 应用程序。 .Net 框架(.Net Framework)能编写出下面类型的应用程序: ①Windows 应用程序 ②Web 应用程序 ③Web 服务 常用的C# 编程的开发工具:Visual Studio(VS:可视化工作室) C#程序结构 一个 C# 程序(C# 文件的后缀为 .cs)主要包括以下部分

mlc_WTMOTW的博客 4978

Linux中断子系统(四)-Workqueue

Workqueue工作队列是利用内核线程来异步执行工作任务的通用机制;Workqueue工作队列可以用作中断处理的机制,利用进程上下文来执行中断处理中耗时的任务,因此它允许睡眠,而Softirq和Tasklet在处理任务时不能睡眠;来一张概述图在中断处理过程中,或者其他子系统中,调用workqueue的调度或入队接口后,通过建立好的链接关系图逐级找到合适的worker,最终完成工作任务的执行;...

生活需要深度 1493

Flash芯片的VCC上电到可操作时间过长

Flash的VCC上电到操作时间(tVSL)通常有最大值限制,如果超过这个时间,核心风险是状态机不同步和指令锁存错误。比如芯片内部振荡器可能已经尝试启动又休眠了,但主控却在这之后才发送指令,导致完全 misinterpreted。Flash芯片的(从电源上电到可以正常进行读写操作的时间)如果过长,会产生一系列负面影响简单来说,这个时间过长意味着电源上升速度太慢,违反了芯片的要求。

qq_61918649的博客 722

一个workqueue导致的性能问题

本文代码基于linux 4.19.195 笔者最近遇到了一个workqueue导致性能问题,引发了笔者对workqueue机制的探索和思考。 简单的抽象后,问题是这样的: 一共有两个进程,假设称之为a进程和b进程。a进程在等待b进程完成一些工作,b进程在完成工作后会调用相关接口通知a进程。b进程完成工作的流程的最末尾的位置,有如下两个关键步骤: 首先调用schedule_work_on触发一个work 1,b进程只需要触发即可,无需等待work 1完成; 然后再调用work_on_cpu(本质上也是sch

kaka__55的博客 1312

别急着做AI:FDE教你识别真需求,让AI真正落地

人工智能项目在落地过程中,经常出现业务方高喊“我们要做AI”,却说不清具体应用场景的现象。判断一个需求是否值得用AI实现,不能只看技术流行度,而要从问题出现频率、当前替代方案以及可量化业务价值三个维度展开验证。同时需要冷静比较规则引擎与大模型的边界:不是所有语义任务都要靠生成式模型,稳定、可解释且低成本的传统方案往往更具工程性价比。数据闭环也至关重要,缺乏历史样本与反馈回流路径的项目,很难在真实环境中持续优化。针对智能客服、合同审查或企业知识库等典型场景,可借助人机协同与最小代价的用户验证,逐步筛除伪需求,

weixin_42624889的博客 341

告别纯文本RAG:用Dify 1.11.0多模态知识库,5步搭建一个能“读图”的智能客服助手

本文详细介绍了如何利用Dify 1.11.0多模态知识库构建智能视觉客服助手,通过5个步骤实现图片内容理解与专业回复。从准备多模态素材到配置知识库节点,再到设计工作流逻辑和性能优化,帮助开发者快速搭建高效客服系统,显著提升用户体验和问题解决效率。

weixin_30832143的博客 452

linux内核学习笔记

文章目录1. wait_queue_head_t2. wait_queue_t3.状态切换图4.优先级调整4.1 工作队列 1. wait_queue_head_t //定义 struct __wait_queue_head { spinlock_t lock; struct list_head task_list; }; typedef struct __wait_queue_head wait_queue_head_t; //初始化 //进入可中断睡眠等待,让出cpu { wait_queue

blog 265

高通camx进程ExtensionModule::TeardownOverrideSession类型crash问题分析之一:【死锁导致】

摘要:本文分析了一个在相机老化测试中出现的pthread_cond_wait持锁超时导致的ExtensionModule::TeardownOverrideSession崩溃问题。通过crash堆栈和日志分析,发现close阶段存在近1分钟的无响应期。进一步分析trace文件发现存在多线程死锁:ChiFeature2Graph::GenerateSmartErrorCode和ChiFeature2RequestObject::SetCurRequestState两个线程分别持有不同锁并互相等待对方释放。最终

1110

工作队列详解

1.工作队列的创建 INIT_WORK(&work_demo, work_demo_func); workqueue_demo = create_singlethread_workqueue("workqueue demo"); queue_work(work

zhuyong006的博客 3028

深入理解 HTTP 协议中的 Content-Type

是 HTTP 协议中的一个头部字段(Header),用于指示请求或响应中实体主体(body)的媒体类型(Media Type),也称为MIME 类型(Multipurpose Internet Mail Extensions)。

h a 6 6 6 c k 为 你解决复杂难题! 997

knowhere | 第一课:项目导论与环境搭建

摘要 本课程是Knowhere项目的第一课,重点介绍项目整体架构和开发环境搭建。Knowhere定位为AI Agent的文档记忆基础设施,通过解析多格式文档并保留结构化信息(如章节层级、表格语义等),为Agent提供可导航的文档知识。项目采用Python monorepo结构,核心包括: apps/api:FastAPI服务,处理HTTP请求和流程调用 apps/worker:Celery服务,执行文档解析等耗时任务 packages/shared-python:共享基础设施层 课程明确了各层职责边界,并推

weixin_43674738的博客 152

Linux内核架构: workqueue

http://lwn.net/Articles/403891/linux内核中断处理的工作队列workqueue机制工作队列(workqueue)是另外一种将工作推后执行的形式。工作队列可以把工作推后,交由一个内核线程去执行,也就是说,这个下半部分可以在进程上下文中执行。 这样,通过工作队列执行的代码能占尽进程上下文的所有优势。最重要的就是工作队列允许被重新调度甚至是睡眠。 那么,什么情况下使用工

hong 1346

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

linux的工作队列,

一个 struct work_struct 结构体代表了一个实际的工作, 工作再被添加到工作队列之前要指定工作的函数,使用#define INIT_WORK(_work, _func) 宏定义初始化一个工作. _work 是工作的地址._func 是工作的函数.注意: 如果一个工作已经在工作队列中还未执行完成则在此放入则不会再次执行. 还有一点, 一个工作队列中可以放入多个工作,但是一个工作阻塞其他工作也是无法执行.工作初始化好了,就可以把工作添加进工作队列中,工作队列就会自动执行工作了.

p2018_5的博客 572

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

捋一下工作队列workqueue

work queue的使用 struct work_struct work; //先定义一个工作 void func(struct work_struct *work) {} //工作的内容 INIT_WORK(work, func) //初始工作,func绑定到work中 schedule_work(&work); ...

m0_37797953的博客 1478

IDEA的使用指南

IDEA基于java的使用手册,可以最快速的上手,在使用中不断的丰富自己的使用技巧.

13 内核开发-任务调度-Work queues工作队列

内核中调度任务除了tasklet 可以调度任务外,还可以使用workqueue ,内核里面使用 CFS 执行队列里面的任务,所以熟悉workqueue就要先了解 CFS完全公平调度程序 (CFS) 是 Linux 内核中的一种进程调度程序,它旨在为交互式应用程序提供公平且可预测的性能。它于 2007 年引入内核,并逐渐成为 Linux 系统中最常用的调度程序。

jxusthusiwen的专栏 965

[Linux内核驱动]工作队列

工作队列的使用方法和tasklet类似,但是工作队列的执行上下文是内核线程,可以调度和睡眠。使用工作队列构造下面数据表,并通过设备读取。

qq_66623299的博客 791

Linux驱动—CMWQ(Concurrency Managed Workqueue)

在传统工作队列中,每个工作队列都由一个独立的内核线程(kthread)来处理队列中的任务。而CMWQ通过共享内核的kworker线程池来高效管理工作队列的任务,减少线程数量,同时提供更高的并发性。CMWQ(并发管理工作队列)是引入的新的工作队列,其目标是提高系统的并发性能和资源利用率,替代旧的传统工作队列机制。WQ_UNBOUND允许任务在任何可用的CPU上运行,不绑定到特定的CPU,具有更高的灵活性。kworker/是系统中共享的内核工作线程,它们属于CMWQ的线程池。

2401_84888945的博客 974

linux 内核工作队列

linux 内核工作队列 12 / 100

一叶知秋的博客 867

深入C语言底层系列21-工作队列

Linux工作队列机制摘要 工作队列是Linux内核中处理中断下半部任务的灵活机制,核心思想是将延迟任务放入队列,由内核线程在进程上下文中异步执行。其优势包括:支持阻塞操作(如内存分配、互斥锁)、可调度延迟任务、灵活的并发控制(通过max_active参数)以及资源隔离(专用工作队列)。 关键组件包括工作项(work_struct/delayed_work)、工作函数(异步执行的逻辑)和工作队列(管理线程与任务)。内核提供共享队列(简单但缺乏隔离)和专用队列(可定制优先级与并发)。重要标志如WQ_MEM_R

bofeng10的博客 1181

驱动-并发管理工作队列

假设已经了解了共享工作队列,自定义工作队列,突然有个知识点 并发管理工作队列。从字眼上看就是并发处理相关的知识点吧。个人理解:当我们熟悉这个知识点后,在实际应用上面和自定义工作队列就是api 上面创建不一样而已。核心还是在于这样创建 并发管理工作队列 的意义、内核处理方式需要熟悉。并发管理工作队列,字面上讲 其实是一种队列的类型,和自定义工作队列一样定义,创建方式不一样而已。需要严格隔离的实时驱动必须保证特定优先级的任务运行在较旧内核版本(2.6.36之前)有特殊调度需求的专用硬件。

十年饮冰,难凉热血 1120

linux workqueue实现原理

工作队列的设计思想可以类比于现实中的生产流水线 :流水线相当于工作队列中的worklist链表,加工部件相当于中断发生 时所产生的工作序列,工人就是工作者线程。当中断发生时,内核将本次中断延后执行的工作序列,放到worklist工作链表中,唤醒 工作者线程执行工作。工作者线程在执行时可能阻塞;当 worklist 中的工作处理完毕后,工作者线程进入空闲状态。

tugouxp的专栏 872
下一篇: 使用OpenSER构建电话通信系统——第一章(1)
老黑徒
博客等级 码龄23年 9粉丝 22原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值