1.  有些时候内核需要一个异步的进程执行上下文,而工作
    队列(workqueue)可以满足这种需求。

工作队列中的每一个元素都是一个工作项(work item),
    有一个函数与工作项相关,这个函数就是工作项所要处
    理的任务。

内核中有一个专门的线程——被称作worker,来依次执行
    工作队列中的每一个工作项对应的函数,当工作队列为
    空时,这个worker就变为空闲状态(idle),当有新的
    工作项加入到工作队列时,worker又重新开始执行。

2.  在最早的实现中包括两种实现方式,一种是整个系统只
    有一个worker(single thread,ST),另一种是每个
    CPU包含一个worker(multiple thread,MT),每一个
    CPU包含一个属于自己的worker pool 。

这两种实现都引起了系统中对于这种异步上下文的竞争,
    只不过是MT方式的竞争可能更小一些。

因此,内核人员对workqueue作了重新实现,新的实现
    被称作concurrency managed workqueue(cmwq),新的
    实现的特点如下:

* 与之前的API兼容

* 实现了统一的每CPU worker pool,减少了资源的浪
      费,提高了并发的灵活性

* 可以自动调节worker pool和并发的级别

3.  为了简化执行这种异步上下文 ,引入了work item,它
    是一个简单的结构体,包含一个函数指针,这个指针指
    向的函数就是需要在异步上文中执行的函数。

当一个内核子系统或者驱动程序需要在异步上下文中执
    行一个函数时,它首先需要创建一个work item结构体,
    然后将这个结构体加入到工作队列中。

工作者线程(worker thread)负责从工作对列中取出work
    item并执行,直到工作队列中的work item为空。工作
    者线程是由worker-pool管理的。

cmwq的实现在用户接口(即子系统或者驱动程序的使用)
    和后台支持上(即如何管理worker pool以及处理work 
    item)有差别。

每一个CPU上都有两个worker pool,一个是用来处理普
    通的work item,另一个是用来处理高优先级的work item。
    另外还有一些worker pool用来处理未添加到绑定到CPU
    的wq上的work item,这些worker pool的数量是动态的。

可以通过修改工作队列的属性来改变添加到其上的work 
    item的执行行为,例如在哪个CPU上执行、并发限制、优
    先级等。

当一个work item添加到workqueue时,根据函数的参数
    以及要添加到的工作队列的属性就可以确定将由哪一个
    worker pool来执行,并且会将该work item添加到该
    worker pool共享的工作列表中。例如,当一个work 
    item被添加到一个workqueue时,它要么被添加到普通
    的worker-pool的工作列表,要么被添加到高优先级的
    worker-pool的工作列表,这里的两个worker-pool对应
    于添加work item到工作队列的CPU。

管理一个工作者线程池的并发度一直是工作者线程池面
    临的一个重要的问题。cmwq保持了最小的并发度,但是
    又让CPU不会空闲,充分利用了CPU资源。

每一个绑定到CPU的线程池通过在调度器中添加钩子实
    现了并发的控制。当一个工作项被唤醒或者睡眠的时候,
    工作者线程池都会接到通知,以此来追踪当前并发的工
    作者线程数。一般来说,当一个CPU上有一个或者多个
    工作者线程在执行的时候,与该CPU绑定的工作者线程
    池不会再起动其他的工作者线程,当该CPU上最后一个
    工作者线程睡眠后,立刻启动一个新的工作,来保证CPU
    不会空转。

对于未绑定到CPU的工作队列来说,它的线程池数量是
    动态的。可以通过apply_workqueue_attrs函数来设置这
    个未绑定的工作队列的参数,系统会自动生成与这些参
    数对应的工作者线程池。另外对于绑定的工作队列可以
    设置某些参数,让某个工作队列忽略并发的限制。

任何需要多个工作者线程同时执行的子系统或者驱动程
    序都需要使用有急救工作者线程(rescuer worker)的
    工作队列。例如,在内存回收的时候,回收内存的工作
    项往往需要同时执行,因此如果没有使用这种工作队列
    的话,就会造成死锁,因为后执行的工作者线程会等待
    前面的工作者线程被释放。

4.  应用程序接口(API)
    
    alloc_workqueue负责创建一个工作队列,之前的create_*workqueue
    之类的接口已经被丢弃了。该函数有三个参数@name,
    @flags以及@max_active,@name表示该工作队列的名字,
    如果急救工作者线程也存在的话,那么@name也是该急救
    工作者线程的名字。

工作队列已经不再管理执行资源,但是它作为一个域用
    来管理工作项,例如保证工作项往前执行、flush以及
    工作项的属性。@flags和@max_active参数控制工作项
    的执行资源分配,如何被调度以及如何执行。

@flags:

WQ_UNBOUND
    未绑定的工作队列对应的工作者线程池数是动态的。该
    工作者线程池未绑定到任何的CPU,因此相当于是一个简
    单的执行上下文的提供者,它会立即执行添加到该工作
    队列工作项。一般在下面两种情况会用到:
    
    * 工作者线程的并发级别波动很大,且将工作项添加到
      工作队列的发起者会在不同的CPU之间来回执行,因
      此如果不使用未绑定工作队列的话,就会造成在各个
      CPU的工作者线程池上创建了许多不会使用的工作者
      线程。
        
    * 当CPU的负担很重时,最好将工作项添加到位绑定的工
      作队列,由调度器来进行调度。

WQ_FREEZABLE
    当系统暂停时,工作队列会进入到冻结状态。并且会清
    空该工作队列中的工作项,直到被解冻才可以执行新的
    工作。

WQ_MEM_RECLAIM
    任何可能在内存回收路径上使用的工作队列都必须设置
    该标记,它保证了不管内存压力有多大,都至少有一个
    执行上下文与之对应。

WQ_HIGHPRI
    高优先级工作队列的工作项被加入到相应CPU的高优先
    级工作者线程池。高优先级工作者线程池由提高了nice
    级别的线程来服务。
    
    普通的工作者线程池和高优先级的工作者线程池是隔离
    的,他们之间不进行任何的交互。对于并发级别的控制
    也是各自独立进行控制的。

WQ_CPU_INTENSIVE
    这种工作队列中的工作项并不受并发级别的控制,因为
    该类型的工作项通常会需要很多的CPU使用量,因此最
    好的办法就是由系统调度器来进行调度。

另外,并发级别的限制会影响密集型工作项的执行,例
    如当前正在运行的非密集型的工作会延迟密集型工作的
    执行。

该标记对未绑定的工作队列是无效的。

@max_active:

表示每个工作队列同时最多能有几个工作项在同一个CPU
    上运行。例如,max_active=16,表示同时最多能有16个
    该工作队列的工作项在每一个CPU上运行。

对于绑定的工作队列,@max_active的最大值为512,默
    认情况下,该参数传值为0,此时它的最大值为256。对
    于未绑定的工作队列,max_active的最大值要大于512。

工作队列的同时处于活跃状态的工作项的数目是由用户
    调节的,例如用户同时添加到工作队列中的工作项的数
    目。除非有需求调节活跃工作项的数目,否则,推荐该
    参数赋值为0。
 
    有些需要依赖ST工作队列的顺序,因此可以使WQ_UNBOUND
    和@max_active为1。这样就模拟了ST,每一个该类型的
    工作项都应该被添加到未绑定的工作队列中,且一次只
    能有一个工作项执行就限定了执行的顺序。

5.  指导方针

* 如果工作队列中的工作项可能用在内存回收代码路径
      中,一定要设置WQ_MEM_RECLAIM,每一个该类型的队
      列都有一个保留的执行上下文。另外,如果在内存回
      收路径中有多个工作项相互依赖的话,应该将这些工
      作项添加到不同的工作对列中。

* 如果没有特殊要求的话,推荐@max_active参数的值
      为0。

* 一般如果没有执行次序要求的话,不会用到ST。

* 工作队列作为工作项一个域,用来WQ_MEM_RECLAIM,
      flush以及某些工作项的共有属性。如果工作项不会
      用到上面的任何一个特性,可以使用系统工作队列。

* 除非一个工作项要耗费很多的CPU,一般将工作项添
      加到绑定的工作队列中。
   
ref
===
1. Documentation/workqueue.txt

工作队列 ( workqueue )相关推荐

  1. 工作队列 order linux,linux 工作队列(workqueue)

    在处理内核相关工作中, 我们经常看到工作队列(workqueue)的身影. 本文描述何为 linux workqueue. 本文基于 2.6.32 的内核, 此时的工作队列还不是 cmwq. 为什么使 ...

  2. 内核工作队列workqueue 简述

    笔记参考自: https://my.oschina.net/kaedehao/blog/631394 https://blog.csdn.net/bullbat/article/details/741 ...

  3. 一种消息和任务队列——beanstalkd

    beanstalkd 是一个轻量级消息中间件,其主要特性: 基于管道  (tube) 和任务 (job) 的工作队列 (work-queue):d 管道(tube),tube类似于消息主题(topic ...

  4. Linux驱动修炼之道-SPI驱动框架源码分析(上)

    Linux驱动修炼之道-SPI驱动框架源码分析(上)   SPI协议是一种同步的串行数据连接标准,由摩托罗拉公司命名,可工作于全双工模式.相关通讯设备可工作于m/s模式.主设备发起数据帧,允许多个从设 ...

  5. beanstalkd消息队列在生产环境的应用

    Beanstalkd 是一个高性能的消息队列中间件,本博文宅鸟将介绍一下这个东东的使用. 一.先通过概念让大家了解Beanstalkd的特性和工作场景. Beanstalkd 是一个轻量级消息中间件, ...

  6. sd 卡驱动--基于高通平台

    点击打开链接 内容来自以下博客: http://blog.csdn.net/qianjin0703/article/details/5918041 Linux设备驱动子系统第二弹 - SD卡 (有介绍 ...

  7. linux内核微妙时,Linux内核模块时间同步函数汇总

    在linux内核模块中能用到的函数比用户空间多,但是它的函数往往被用得很少.当然在内核中叶可以调用用户空间的函数只要直接调用系统调用的封装函数就行,如下: 如调用long gettimeofday(s ...

  8. java高级应用:线程池全面解析

    什么是线程池? 很简单,简单看名字就知道是装有线程的池子,我们可以把要执行的多线程交给线程池来处理,和连接池的概念一样,通过维护一定数量的线程池来达到多个线程的复用. 线程池的好处 我们知道不用线程池 ...

  9. java线程池应用的好处_java高级应用:线程池全面解析

    什么是线程池? 很简单,简单看名字就知道是装有线程的池子,我们可以把要执行的多线程交给线程池来处理,和连接池的概念一样,通过维护一定数量的线程池来达到多个线程的复用. 线程池的好处 我们知道不用线程池 ...

最新文章

  1. 最全的MAC端截图工具推荐,寻找适合自己的截图工具
  2. php5.6 64位配置,centos(64位) 安装PHP5.6,配置LNMP
  3. clion 带参数调试运行
  4. python开源项目博客_Blog_mini首页、文档和下载 - Python Flask开源博客 - OSCHINA - 中文开源技术交流社区...
  5. 数据中台建设常见的几大误区,如何规避,你需要知道这几点
  6. 用Unity实现游戏弹反效果
  7. OpenGL:纹理Textures
  8. 参加Sun公司的新产品的发布会议
  9. 计算机学院特色迎新标语,2019大学各学院开学迎新创意标语 2019各大学网红创意迎新宣传标语...
  10. RabbitMQ学习之集群模式
  11. img 标签的 src 属性
  12. Linux下MySQL数据库的备份与还原
  13. labview如何安装modbus离线模块_Chrome73如何下载和安装扩展离线文件crx
  14. 适合初学者的大数据学习路线
  15. 计算机操作系统的自举过程
  16. 未来互联网+大数据时代
  17. QQ空间导出助手插件
  18. 用canvas写 看你有多色 游戏
  19. SAE使用以及GPS 的经纬度换算成距离的代码(转载)
  20. 智源AI日报(2022-08-30): 华为谢凌曦:关于视觉识别领域发展的个人观点

热门文章

  1. [转载] python中union函数_如何掌握Python union()方法及怎么用?
  2. SDR与DDR的区别
  3. HDU 5729 Rigid Frameworks (联通块计数问题)
  4. django中使用第三方包实现定时任务
  5. Angularjs1培训
  6. SSH如何通过公钥连接云服务器
  7. Java学习之道:Java中十个常见的违规编码
  8. Windows 2008 R2 安装 Windows phone 7 开发环境
  9. Grad-CAM: Visual Explanations from Deep Networks via Gradient-based Localization
  10. LeetCode-7.整数反转(越界问题)