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


在非常早曾经,大概是2009年的时候。写过一篇关于Linux RCU锁的文章《RCU锁在linux内核的演变》,如今我承认。那个时候我尽管懂了RCU锁,可是我没有能力用一种非常easy的描写叙述把Linux的实现给展示出来,有道是你能给别人用你自己的方式非常简洁地描写叙述清楚,你才是真正的精通它。否则,无异于背诵。换个说法,假设你在被面试。在短时间内靠嘴说给面试官,且他还要能听明白,就说明自己真的懂了,这样的时候,是不会给你机会分析源码的,也不可能让你背诵源码。
       时隔五年多,最近又碰到了这个话题,我不能自诩自己对RCU锁是多么精通,可是起码,和2009年相比,我确实有所进步,因此在这个台风肆虐的次日,我尝试着用我自己的方式描写叙述一下Linux对RCU锁的一种实现方式,作为《RCU锁在linux内核的演变》这篇文章的补充。本文不配图,没代码,仅仅是文字。
声明:假设你还不知道RCU锁是什么。请自行baidu,本文不再赘述概念。可是这也就等于说,假设我自己有一天忘记了RCU。我也不能指望从本文中得到不论什么帮助。我总是这样,不是吗?能力在忘不在记。得其义而忘其形。


RCU要素

RCU锁的要素包含

读标志

假设一个Reader企图占领一把RCU锁,它是不须要付出不论什么代价的,仅仅须要设置一个标志,让外界知道有Reader在占领这把RCU锁。多个Reader能够共同持有一把RCU锁。

写时拷贝

假设有一个Write企图更新RCU锁所保护的数据,那么它会首先查看该RCU锁的读标志,假设有该标志,说明有最少一个Reader持有了该RCU锁。它须要对原始数据make a copy,写这个副本并将更新过的副本保存在某处,等待时机用该副本更新原始数据。

更新时机

这个时机就是用副本更新原始数据的时间点。这个时间点怎样确定是RCU锁实现的算法核心,它直接能够确定全部的数据结构。确切来讲,Writer必须waitting for all readers leaving,方可Update原始数据,问题是,它是怎么知道全部的Reader都离开了呢?

Linux内核对RCU锁的几种实现

1.原始实现-利用抢占禁止

Linux内核于2.6内核引入了RCU锁的概念。在第一个版本号中,它利用了抢占禁止的方式来标志有Reader持有RCU锁,这意味着期间不能发生task切换(指的是task_struct所代表的sched entity切换)。

那么全部Reader均已经释放RCU锁的标志就是。task切换了,因此非常easy,用副本Update原始数据的时机就是task切换时。
       全部的Write会将自己写的副本挂在一个list上,在task切换的时候会touch这个list,假设该list非空,则遍历每个元素。Update原始数据。

评价[该部分与实现无关,纯形而上的,能够忽略]      

这就是第一版的原始实现。它是否合理姑且不论。确实。它能够工作。可是:
a.它这样的实现是否会影响调度子系统的时延
b.因为禁用抢占,抢占粒度变粗,对交互性是否会有影响
c.对CPU间的task负载均衡的影响呢
我们发现,因为RCU的这个实现不是靠自身机制实现的,它不可避免地会影响到系统的核心机制。比方调度,负载均衡等,这意味着它不能长久。也无法经历复杂的演变。因为随着它在这条路上的逐步演进,对系统核心机制的影响将越来越大,故而,它必须从系统层面剥离出来。确实,它也是这么做的。这就是第二代RCU实现-可抢占RCU锁。

2.新实现-利用阶段计数器

须要一种更加有效的方式来标志Reader已经持有锁-第一要素读标志,而且这个标志要尽可能精确,且不能使用系统核心的机制,要做成全然封闭的闭环,不依靠外部当然也就不会影响外部。
       纯天然的想法就是使用计数器,每一把RCU持有一个Reader计数器,一旦有Reader前来持锁。仅仅须要一个原子操作,将该计数器加1就可以,Writer写数据时。发现计数器不是0就意味着须要make a copy了-第二要素写时拷贝(COW-Copy On Write)。

如今的问题是第三要素,Writer怎么知道全部的Reade都已经将锁释放了呢??
       纯天然的想法就是在某个Reader释放锁的时候,计数器减1。当计数器又一次变为0的时候。这就是副本更新原始数据的时机。

确实是这样,可是依照持锁和解锁的分布看,它们应该是均等的,这意味着计数器的值会在一个期望值上下波动,变成0的希望及其渺茫,因此须要引入还有一个參量,即阶段。
       将唯一的那个RCU计数器分裂为两个计数器:old readers和new readers。


       太初,任选某一个时刻,将RCU锁当前的计数器(称为原始计数器)值复制一份存入old readers,计数器清0,原始计数器改称为new readers。复制结束的当下,new readers计数器为0,old readers计数器为现阶段持有锁的reader的数量。而且持锁者task(即task_struct)与RCU锁之间保持关联(难道不是一个task_struct字段能够搞定的吗?)。task永远知道自己是new reader还是old reader。


       此时,就能够明白定义lock和unlock的行为了:
lock--设置自己的task为new reader,将RCU的new reader计数器加1。


unlock--获取自己的task是new reader还是old reader,将自己所在的reader计数器减1。
此时非常明白的事实是。old reader计数器总是会递减而不会递增,而new reader不但会递增也会递减。这样,选择Update的时机也非常明白了,那就是,old reader计数器变为0,这个时刻,就该将全部的副本覆盖原始数据了。
       如今总结全部的三个要素:

读标志

为该RCU锁的new reader计数器加1

写时拷贝

假设该RCU锁的old reader计数器不为0,则运行写时复制。

更新时机

每次unlock操作,都会将本task的reader计数器(或者是new reader。或者是old reader)减1。一旦该RCU锁的old reader计数器变成0。则运行全部的Update操作。

评价[该部分与实现无关,纯形而上的。能够忽略]

持有RCU锁的reader。能够睡眠,能够被抢占。能够调度到别的CPU上,全然是封闭的,和系统其他的机制无关。

然而。我一直在思考一个更好的实现,仅仅因疯子不给力。!


3.RCU Tree实现(实在是没有2好)

今天实在没有时间了,要出去。兴许补充。

转载于:https://www.cnblogs.com/wzjhoutai/p/7202772.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/400481.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

sublime_text 3 注册序列号

为什么80%的码农都做不了架构师?>>> ----- BEGIN LICENSE ---- Andrew Weber Single User License EA7E-855605 813A03DD 5E4AD9E6 6C0EEB94 BC99798F 942194A6 02396E98 E62C9979 4BB979FE 91424C9D A45400BF F6747D88 2FB88078 90F5CC94 1CDC92DC 845…

【51单片机快速入门指南】3.2.1:PWM、呼吸灯与舵机

目录硬知识PWM(脉冲宽度调制)基本原理脉宽调制分类上机实战呼吸灯main.c中断服务函数修改TIM.c中的中断服务函数效果开发板电路分析舵机控制舵机控制方法main.c中断服务函数修改中断服务函数舵机测试程序main.c效果普中51-单核-A2 STC89C52 Keil uVisio…

Oracle常用查看表结构命令

转载自:http://blog.520591.com/1301 获取表: select table_name from user_tables; //当前用户的表 select table_name from all_tables; //所有用户的表 select table_name from dba_tables; //包括系统表 select table_name from dba_tables where owner’用户名…

Centos7 安装oracle数据库

参考的内容: http://docs.oracle.com/cd/E11882_01/install.112/e24325/toc.htm#CHDCBCJF http://www.cnblogs.com/yingsong/p/6031452.html http://www.cnblogs.com/yingsong/p/6031235.html 步骤主要是有: 1、安装依赖的 软件包 2、创建用户和目录&…

ABAP常见面试问题

ABAP常见面试问题 1. What is the typical structure of an ABAP program? 2. What are field symbols and field groups.? Have you used "component idx of structure" clause with field groups? 3. What should be the approach for writing a BDC program? …

车牌识别之车牌定位(方案总结)

尊敬原作者,转自:http://blog.csdn.net/hqw7286/article/details/5810353 一直研究车牌识别算法,主要关注车牌定位和字符识别。我想分享一下我对车牌定位的看法。 从根本上讲,车牌定位的算法分为三类,一类是基于边缘的&#xff0c…

Proteus仿真单片机:51单片机的仿真

目录新建工程调试在Proteus中编写程序导入Keil生成的Hex程序Windows 10 20H2 Proteus 8 Frofessional v8.9 SP2 Keil uVision V5.29.0.0 PK51 Prof.Developers Kit Version:9.60.0.0 新建工程 设置名称和路径 下一步 下一步 选择系列、控制器和编译器 双击MCU设置主频 …

CentOS多网卡重命名配置

CentOS多网卡重命名配置在CentOS7中我安装了3块网卡,但是名字是enoxxxxx的格式,让我这个有强迫症的***座很是不爽,以下是我配置网卡并且重命名为ethx的详细步骤前提工作要做好:1.查看网卡UUID# nmcli con show名称 UUID …

Linux 命令行输入

这几天刚刚接触到Linux,在windows上安装的VMWare虚拟机,Centos7。安装什么都是贾爷和办公室的同事帮忙搞定的。 在虚拟机界面,按快捷键CtrlAltEnter,可以全屏显示Linux界面,再按一次则退出全屏。 如何在Linux里输入命令…

【51单片机快速入门指南】2.5:并行I/O扩展与8255A

目录硬知识单片机I/O扩展基础知识I/O接口电路的功能速度协调输出数据锁存数据总线隔离数据转换增强驱动能力单片机并行扩展总线并行扩展总线的组成80C51单片机并行扩展总线I/O编址技术可编程并行接口芯片82558255硬件逻辑结构口电路总线接口电路A组和B组控制电路中断控制电路82…

24小时制时间格式和12小时制时间格式

yyyy-MM-dd HH:mm:ss -------24 yyyy-MM-dd hh:mm:ss -------12转载于:https://www.cnblogs.com/hbhzz/p/3165370.html

win 下 apache2.4 +tomcat7 集群

为什么80%的码农都做不了架构师?>>> 反正每次来做一个不熟悉的东西,就是各种的search ,前一次去做过一个apache的东西,各种蛋疼,各种不能用。好多的东西也是比较旧了的咯。 这次结合前辈的各种东借西拿,总…

Proteus常见电平状态

目录高态其他低态Windows 10 20H2 Proteus 8 Frofessional v8.9 SP2 摘自proteus常见状态 —— 山科董国正 高态 PHI 电源高态:电源高逻辑SHl 强电高态:主动输出高逻辑WHI 弱电高态:被动输出高逻辑 其他 FLT 悬空态:悬空输出…

简单理解正则表达式

我理解的正则表达式: 正则表达式就是用于字符(串)匹配时的一种描述字符串的表达式。 关于正则表达式: 预定义的字符类 用\d可以匹配一个数字;用\D表示非数字字符[^\d]用\w可以匹配一个字母或数字;用\W表示非…

最后一行数据

最后一行数据 设计要点:导入外部数据、SQL、数据源、汇总行 秀秀:既然你说第一行的数据那么重要,那俺觉得最后一行数据也很重要。 阿金:为什么? 秀秀:因为最后一行数据往往是汇总行,一般引用数据…

Proteus仿真单片机:PIC18单片机的仿真

目录新建工程ProteusMPLAB X IDE调试Windows 10 20H2 Proteus 8 Frofessional v8.9 SP2 MPLAB X IDE v5.45 新建工程 Proteus 下一步 下一步 选择芯片、编译器 搭建实验电路 MPLAB X IDE MPLAB X IDE 新建工程 选择独有项目 选择芯片 选择编译器 配置工程名称、路…

Realm学习总结

参考博客: http://www.jianshu.com/p/096bec929f2a http://www.cnblogs.com/ilyy/p/5648051.html 参考的博客介绍很详细,我就不写了..写了一个简单的学习的demo. GitHub地址: https://github.com/PengSiSi/RealmDemo 代码如下: // // ViewController.m // RealmDemo // // C…

with(nolock)的用法

with(nolock)的介绍 大家在写查询时,为了性能,往往会在表后面加一个nolock,或者是with(nolock),其目的就是查询是不锁定表,从而达到提高查询速度的目的。 当同一时间有多个用户访问同一资源,并发用户中如果有用户对资源做了修改,此时就会对其它用户产生某些不利的影…

干支表

原文地址:http://114.xixik.com/tiangandizhi/ 天干 12345678910甲乙丙丁戊己庚辛壬癸地支 123456789101112子丑寅卯辰巳午未申酉戌亥六十年甲子(干支表) 12345678910甲子乙丑丙寅丁卯戊辰己巳庚午辛未壬申癸酉11121314151617181920甲戌乙亥丙…

【PIC18单片机学习笔记】一、程序的烧录

目录编程器烧录软件烧录准备程序main.cpic18.h烧录效果Windows 10 20H2 PICkit 3 v3.10 MPLAB X IDE v5.45 PIC18F46J50 编程器 所用编程器为PICkit 3.5 按图示连接好编程器和开发板 烧录软件 所用烧录软件为PICkit 3 v3.10 初次使用需要给编程器更新固件&#xff0c…