linux rcu锁的使用

 

 

 

 

 

https://blog.csdn.net/xuchenhuics/article/details/78777347?utm_medium=distribute.pc_relevant.none-task-blog-baidujs_title-0&spm=1001.2101.3001.4242

网上RCU相关的技术博客比较多,先列几个可供参考的:

MagicBoy201写的《再谈Linux内核中的RCU机制 》http://blog.chinaunix.net/uid-23769728-id-3080134.html

这篇博客写的比较宏观一些。

《linux内核 RCU机制详解》 http://blog.csdn.net/xabc3000/article/details/15335131

原文没找到,这篇博文看看前段就好,了就下什么是RCU和宽限期。

<深入浅出> linux内核 RCU (一)经典RCU》http://blog.csdn.net/chenyu105/article/details/7910269

<深入浅出> linux内核 RCU (二)分级RCU》http://blog.csdn.net/chenyu105/article/details/23104221

这两篇博文 经典RCU写的很不错,把经典RCU的逻辑实现都写出来了。

RCU (Read-Copy Update)是一种同步机制,是对读写锁的优化。

先简单了解一下读写锁,rwlock可以多个线程同时占用读模式的读写锁,但是只能一个线程占用写模式的读写锁,即

(1)当有人拿到写锁的时候,任何人都不能再拿到读锁或写锁

(2)当有人拿到读锁的时候,其他人也可以拿到读锁,但不能有人拿到写锁去修改临界区

(3)已经加了读锁时,如有人尝试拿写锁,需要尽快得到满足,避免写锁饥饿

RCU的行为方式

(1)随时可以拿到读锁,即对临界区的读操作随时都可以得到满足

(2)某一时刻只能有一个人拿到写锁,多个写锁需要互斥,写的动作包括 拷贝--修改--宽限窗口到期后删除原值

(3)临界区的原始值为m1,如会有人拿到写锁修改了临界区为m2,则在写锁修改临界区之后拿到的读锁获取的临界区的值为m2,之前获取的为m1,这通过原子操作保证

对比发现RCU读操作随时都会得到满足,但写锁之后的写操作所耗费的系统资源就相对比较多了,并且只有在宽限期之后删除原资源。

RCU宽限期:

 图中每行代表一个线程,最下面的一行是删除线程,当它执行完删除操作后,线程进入了宽限期。宽限期的意义是,在一个删除动作发生后,它必须等待所有在宽限期开始前已经开始的读线程结束,才可以进行销毁操作。这样做的原因是这些线程有可能读到了要删除的元素。图中的宽限期必须等待1和2结束;而读线程5在宽限期开始前已经结束,不需要考虑;而3,4,6也不需要考虑,因为在宽限期开始后的线程不可能读到已删除的元素。

宽限期的描述来源于《linux内核 RCU机制详解》 http://blog.csdn.net/xabc3000/article/details/15335131

宽限期的定义引来几个问题(后文称RCU问题)

(1)宽限期的开始即预示着RCU监测的开始,需要监测宽限期开始之前的线程是否结束

(2)宽限期是否在调用call_rcu之后马上开始?答案是否定的,同一时刻只有一个宽限期,在某个宽限期内新加入的所有call_rcu回调会合并为一个宽限期,在此宽限期到期后

一起得到调用,即下图中右边所示

(3)如何判断一个宽限期到期

经典(classic)RCU读锁就是关内核抢占,读锁释放时再开内核抢占,因此判断运行在某CPU上线程是否有释放读锁的一个间接方式就是观察这个CPU上是否发生了调度(该CPU一直idle状态需额外处理),这种判断方式简单而暴力,在非抢占内核中实时性肯定不是很好,但总体的开销要比释放读锁后再发一个直接的“通知”要小。因此开启一个宽限窗口后,如果监测到所有的CPU在监测点之后都发生过一次调度则就可以认为宽限期到期了,就可以释放原始数据了,太简单暴力了,可能某些CPU上运行的线程跟这个宽限窗口所服务的RCU一点关系都没有,可RCU就是做的这么暴力,这也是一些应用场景需要解决的问题,通过修改RCU的监测机制是能做到不这么暴力的。

RCU要实现的逻辑是:

(1)用户注册RCU回调(call_rcu)

(2)将新注册的RCU回调放到一个缓冲队列(链表)中,或正式队列中为空时直接放到一个正式队列中

(3)在时钟中断---软中断中判断如没有一个有效的宽限窗口存在,而用户有发起“开窗”请求(上述链表非空),则开启一个宽限窗口,开始监测系统中所有的CPU是否有调度(通过位图、per cpu变量)

(4)在时钟中断---软中断中监测到宽限期到后(所有CPU都发生了调度),则执行RCU回调/激活RCU软中断

(5)为解决RCU问题2,CPU过多时操作位图引起的cache line问题、竞争问题,软中断超长等等问题,RCU具体实现的时候应用了一些比较巧妙的方式,来提高RCU的性能

(6)以上行为(1);(2)(3)(4)周而复始。

 

RCU一直在优化,2.6.25 ,2.6.34,3.10,4.1,不同版本的RCU实现已经有比较大的区别了,早起版本理解起来更直观一些,

有兴趣的话可以上http://lxr.oss.org.cn/快速浏览一下早起的代码。

后面计划再结合3.10和4.1内核赏析一下RCU的实现,体味一下RCU作者的匠心。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值