kernel中有两个rcu的实现,一个是tiny rcu,另一个是tree rcu。这两种rcu的前身都是classic rcu。
如果要阅读classic rcu的实现代码,必须找kernel 2.6.26,因为在kernel 2.6.27,classic rcu开始转型为使用tree node的scalable classic rcu,是现在的tree rcu趋形。
那么tiny rcu与classic rcu又是什么关系呢,tiny如其名,就是紧凑的classic rcu,专门为单cpu(uniproceesor)的嵌入系统(内存十分有限)而设计的。换句话说,相当于classic rcu的删减版。

classic rcu使用全局状态rcu_ctrblk,提供两个flaver的全局状态rcu_sched_ctrblk和rcu_bh_ctrblk。
tiny rcu沿用这两个全局状态,并将SMP部分的内容删减。
tree rcu则是将rcu_ctrblk演进成分层(hierarchical)结构,也就是树形。全局状态rcu_state,分层(树型)节点rcu_node,cpu独立状态rcu_data,以及cpu空闲变频状态rcu_dynticks。将原本在rcu_ctrblk的cpumask,以分层的方式分置到rcu_node的qsmask。

现在tree rcu包含了许多特性,初涉者不容易在庞大的结构体成员和众多特性功能的函数逻辑中分离出,与设计文档描述相吻合的(纯净或原始的)路径进行研究。
设计文档中描述了classic rcu就是kernel 2.6.16为止的rcu实现,而tree rcu的趋形就是从kernel 2.6.17开始。如果你对现在的kernel中的rcu实现感到迷惑的话,可以选择上面提到的两个版本的kernel的rcu进行比较来研究。
或者你可以参考第一份scalable classic rcu提交的日志文档,在LWN网站。文档以git diff的方式,更好地展现了classic rcu如何向tree rcu演进。
但是你不可能很好地从tiny rcu去研究classic rcu,虽然说tiny rcu是classic rcu的精简,但是已经将SMP部分实现基本去除(比如qsmask),而tree rcu和classic rcu同是基于SMP的实现。
因此如果你将tiny rcu作为classic rcu去同tree rcu进行比较时,你会根本找不到SMP相关部分的影子,差异巨大而找不出演进的连接点(相关性),从而迷惑。

classic rcu的rcu_ctrblk中有我们熟知的rcu文档描述的qsmask,用于维护(或感知)一个gp。而tree rcu则是将这个qsmask进行分层,tiny rcu却是将这个qsmask丢弃。如果你不清楚这一点,当你比较tree rcu和tiny rcu时,中间就会有断层,联系不上。
这是因为tiny rcu限定了单CPU(uniprocessor)的条件。在tiny rcu实现中并没有任何per cpu变量。并且在cpu提交一次qs的同时,就会发起rcu softirq,换句话说,gp并没有另外进行维护管理,只是简单地将gp等同于每次qs的提交。

classic rcu和tree rcu同样都使用nxtlist和nxttail来维护4段rcu callbacks的 batch处理。而tiny rcu将其精简为rcucblist,以及donetail和curtail这样形式的2段rcu batch,并且简化当中的维护。
当使用者调用synchronize_sched或call_rcu时,同步(或者说是延后)的回调就会链到cur段。当调度器scheduler提交一次qs时,就会将cur段的回调纳入done段,并发起rcu softirq。当内核kernel处理rcu softirq就会从done段将回调batch处理。
由此我们不容易发现tiny rcu在维护gp和qs。

tiny rcu和tree rcu是classic rcu不同方向的结果,tiny rcu为uniprocessor且资源有限的嵌入场合而去简化(剦切)了classic rcu,另外tree rcu则是使classic rcu向前朝超级多cpu(在rcu文档中,a few of hundren表示数百cpu还不值一提,起码也要成千上万,当时2008年)的场合,演进更高效更稳定。
kernel 2.6.27是分水岭,classic rcu向tree rcu演进。tiny rcu和tree rcu同是2008年的产物。
在kconfig中,tree rcu是默认的rcu。如果需要preempt rcu的话,必须使用tree rcu。换句话说,tiny rcu不支持preempt rcu。

scalable classic RCU implementation》kernel 2.6.27 第一份基于tree node分层的classic rcu代码提交日志文档。

Hierarchical RCU

RCU: The Bloatwatch Edition》tiny rcu的设计文档。

Simplifying RCU》kernel 3.11 移去CONFIG_PREEMPT_TINY,即移去preempt tiny rcu。

linux内核的tiny rcu, tree rcu的更多相关文章

  1. 大话Linux内核中锁机制之RCU、大内核锁

    大话Linux内核中锁机制之RCU.大内核锁 在上篇博文中笔者分析了关于完成量和互斥量的使用以及一些经典的问题,下面笔者将在本篇博文中重点分析有关RCU机制的相关内容以及介绍目前已被淘汰出内核的大内核 ...

  2. Linux内核中锁机制之RCU、大内核锁

    在上篇博文中笔者分析了关于完成量和互斥量的使用以及一些经典的问题,下面笔者将在本篇博文中重点分析有关RCU机制的相关内容以及介绍目前已被淘汰出内核的大内核锁(BKL).文章的最后对<大话Linu ...

  3. linux 内核 RCU机制详解

    RCU(Read-Copy Update)是数据同步的一种方式,在当前的Linux内核中发挥着重要的作用.RCU主要针对的数据对象是链表,目的是提高遍历读取数据的效率,为了达到目的使用RCU机制读取数 ...

  4. Linux内核同步:RCU

    linux内核 RCU机制详解 简介 RCU(Read-Copy Update)是数据同步的一种方式,在当前的Linux内核中发挥着重要的作用.RCU主要针对的数据对象是链表,目的是提高遍历读取数据的 ...

  5. linux内核 RCU机制详解【转】

    本文转载自:https://blog.csdn.net/xabc3000/article/details/15335131 简介 RCU(Read-Copy Update)是数据同步的一种方式,在当前 ...

  6. Linux内核中锁机制之完成量、互斥量

    在上一篇博文中笔者分析了关于信号量.读写信号量的使用及源码实现,接下来本篇博文将讨论有关完成量和互斥量的使用和一些经典问题. 八.完成量 下面讨论完成量的内容,首先需明确完成量表示为一个执行单元需要等 ...

  7. 大话Linux内核中锁机制之完成量、互斥量

    大话Linux内核中锁机制之完成量.互斥量 在上一篇博文中笔者分析了关于信号量.读写信号量的使用及源码实现,接下来本篇博文将讨论有关完成量和互斥量的使用和一些经典问题. 八.完成量 下面讨论完成量的内 ...

  8. Linux内核同步 - RCU synchronize原理分析

    RCU(Read-Copy Update)是Linux内核比较成熟的新型读写锁,具有较高的读写并发性能,常常用在需要互斥的性能关键路径.在kernel中,rcu有tiny rcu和tree rcu两种 ...

  9. Linux内核RCU(Read Copy Update)锁简析

    在非常早曾经,大概是2009年的时候.写过一篇关于Linux RCU锁的文章<RCU锁在linux内核的演变>,如今我承认.那个时候我尽管懂了RCU锁,可是我没有能力用一种非常easy的描 ...

随机推荐

  1. 手动部署 Docker+Grafana+Prometheus系统监控之Redis

    监控规划图 使用Docker 创建两台Redis docker run -d --name redis1 redis docker run -d --name redis2 redis 查看redis ...

  2. Spring 框架基础(04):AOP切面编程概念,几种实现方式演示

    本文源码:GitHub·点这里 || GitEE·点这里 一.AOP基础简介 1.切面编程简介 AOP全称:Aspect Oriented Programming,面向切面编程.通过预编译方式和运行期 ...

  3. vue系列---Mustache.js模板引擎介绍及源码解析(十)

    mustache.js(3.0.0版本) 是一个javascript前端模板引擎.官方文档(https://github.com/janl/mustache.js) 根据官方介绍:Mustache可以 ...

  4. logistic回归 python代码实现

    本代码参考自:https://github.com/lawlite19/MachineLearning_Python/blob/master/LogisticRegression/LogisticRe ...

  5. 最简破解-java代码热加载热部署IDEA插件JRebel

    如果经济实力允许的话,还是建议大家去购买收费版.支持原创作者,才能有更好的产品出现. 一.Jrebel插件介绍 JRebel一款帮助我们在开发过程中实现热加载的插件,目前来说,在IDEA中实现热加载最 ...

  6. linux下shell脚本启动jar包

    本文采用的jar包是通过idea下maven打包的springboot项目. 写这个shell脚本是为了在linux下方便启动jar包时不用输入太多的shell命令,将启动脚本的一系列shell命令整 ...

  7. FastReport快速实现条形码,二维码面单打印

    一.什么是FastReport? FastReport是功能齐全的报表控件,使开发者可以快速并高效地为·NET/VCL/COM/ActiveX应用程序添加报表支持. FastReport有很多产品,如 ...

  8. .NET进阶篇05-Linq、Lambda表达式

    知识需要不断积累.总结和沉淀,思考和写作是成长的催化剂 内容目录 一.Lambda表达式1.匿名方法2.Lambda表达式二.Linq概述三.查询操作符1.linq初见2.常用查询操作符筛选排序分组连 ...

  9. MySQL的基础与安装

    一.数据库概述 1.什么是数据库? 数据库(Database)是按照数据结构来组织.存储和管理数据的建立在计算机存储设备上的仓库. 2.数据库的主要特点: ⑴ 实现数据共享        数据共享包含 ...

  10. 【原创】go语言学习(十一)package简介

    目录 Go源码组织方式 main函数和main包 编译命令 自定义包 init函数以及执行行顺序 _标识符 Go源码组织方式 1. Go通过package的方式来组织源码 package 包名 注意: ...