并发管理工作队列(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

从零搭建Python接口自动化测试框架:pytest+requests+Allure实战指南

接口自动化测试是现代软件工程中保障交付质量、提升测试效率的核心实践。其基本原理是通过脚本模拟客户端请求,对服务端接口进行自动化的功能验证、性能探测与回归测试,从而替代重复的手工操作。在技术实现上,Python凭借其简洁语法和丰富的生态,成为构建此类框架的主流选择,其中pytest测试框架、requests HTTP库和Allure报告工具构成了技术栈的黄金组合。这套技术方案的价值在于,它能将测试用例数据(如YAML文件)与执行逻辑分离,实现数据驱动测试,并通过持续集成(如Jenkins)无缝融入DevOps

weixin_31822733的博客 378

2024最新版Anaconda Navigator安装使用指南

本文简要介绍如何下载安装Anaconda Navigator最新版,以及如何使用Python内核搭载来完成应用程序开发。

jackson_lingua的博客 1万+

Linux中断子系统(四)-Workqueue

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

生活需要深度 1493

ESP32-P4 GPIO双域架构:HP/LP分离、寄存器级控制与低功耗工程实践

GPIO(通用输入输出)是嵌入式系统中最基础且高频使用的硬件接口,其性能、灵活性与功耗特性直接影响产品实时性与续航能力。现代高性能MCU如ESP32-P4通过HP/LP双电源域分离、可编程IO复用(IO MUX)、信号交换矩阵及硬件自动化机制(如ETM事件、Sigma-Delta调制),将传统GPIO升级为兼具模拟能力、亚微秒响应与微安级待机的智能外设子系统。其核心价值在于实现引脚功能动态重构、中断零延迟处理、Deep-sleep期间自主唤醒与多核安全操作。典型应用场景涵盖工业PLC信号采集、电池供电传感器

weixin_35949153的博客 97

一个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

ENS160传感器原理图设计,已量产(空气质量传感器)

ENS160 是一款集成式数字空气质量传感器,核心优势源于 “MEMS 传感元件 + 内置微处理器” 的架构。

不脱发的程序猿 570

Apollo 9.0 参考线生成器 -- ReferenceLineProvider

在基于参考线的规划算法中,参考线是Planning一切工作的基础和前提,所以搞清楚参考线怎么来的就变得很重要。为此,首先需要了解Planning 与 Routing的交互,通过交互得到路径片段,这些路径片段就告诉我们该怎么走,再在此基础上生成参考线,最后使用不同的平滑算法对参考线进行平滑,得到一条光滑的参考线。

WaiNgai 1665

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

在最新版eclipse中配置使用AI AIcoder _AIcoder配置GPUSTACK使用_配置OLLAMA本地AI模型利用_集合---AI场景应用工作笔记

本文介绍了三款实用的编程辅助工具:一款便捷的反编译插件,可直接在插件市场安装使用;GitHub Copilot提供每月2000次代码补全和50条聊天记录的免费额度,支持智能代码提示功能;aicoder支持配置本地模型运行。这些工具都能有效提升开发效率,其中GitHub Copilot的智能补全功能尤为突出。

添柴程序猿的专栏 1243

工作队列详解

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

zhuyong006的博客 3028

STM32外部中断EXTI原理与飞控实时应用实战

外部中断(EXTI)是嵌入式系统中实现事件驱动和实时响应的核心机制,其本质是将外部电平变化转化为可调度的CPU中断事件。基于ARM Cortex-M NVIC架构,EXTI通过GPIO-EXTI-NVIC三级硬件通路实现低延迟信号捕获,具备边沿触发、优先级管理与挂起控制等关键能力。在四轴飞控、工业传感器、人机交互等对毫秒级响应有强需求的场景中,EXTI显著优于轮询方式,兼顾实时性与CPU资源效率。实际开发需严格遵循SYSCFG映射→EXTI配置→NVIC使能的时序逻辑,并规避常见陷阱如中断号误配、伪触发、低

weixin_36382073的博客 65

PCL RANSAC拟合空间圆【2026最新版】

RANSAC三维点云空间3D圆拟合。博客长期更新,本文最新更新时间为:2026年4月13日。代码在PCL1.15.0中测试通过

点云侠的博客 7455

Linux内核架构: workqueue

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

hong 1346

温度PID控制PLC程序

温度PID稳定控制程序,适用于欧姆龙PLC,对其他PLC也具有很大参考价值

linux的工作队列,

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

p2018_5的博客 572

大中型超市收银系统(可直接运行)

光步前台收银系统系统功能:商品销售、商品退货、挂单、收银员权限、会员销售、单品取消、整单取消、商品查询、脱机销售、脱机数据上传,基本资料下载,开钱箱、小票打印、收款结算,支持多币种付款方式(现金、储值卡、礼券、微信等),支持多种促销。运行环境:.net 4.0登陆信息用户名:1001 密码:123456内置商品信息,商品编码可输入00001000 - 00010000,测试效果相关功能键F5 结算 F9挂单 F11商品查询 F8退货 Insert单品取消 Del整单取消 F12开钱箱F2 会员 Ctrl+Z退出系统 Home 锁屏 相关源码待公开

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

捋一下工作队列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

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

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、付费专栏及课程。

余额充值