2014年(84)
分类: LINUX
2014-05-15 15:29:42
法律声明:《LINUX3.0内核源代码分析》系列文章由谢宝友()发表于http://xiebaoyou.blog.chinaunix.net,文章中的LINUX3.0源代码遵循GPL协议。除此以外,文档中的其他内容由作者保留所有版权。谢绝转载。
1.1 Linux中的无锁编程
关于无锁编程,可以参见这篇文章:
http://www.ibm.com/developerworks/cn/linux/l-cn-lockfree/index.html。
根据这篇文章的观点,spinlock也属于无锁编程的范围。但是在linux中,真正将无锁编程发挥到极致的是RCU和kfifo。
1.1.1 RCURCU全称是READ-COPY UPDATE。其官方网址是:
。
要全面的理解RCU,请参考作者paul的书籍《Is Parallel Programming Hard, And, If So, What Can You Do About It?》。我和鲁阳同学已经将大部分内容翻译成中文,中文稿名为《深入理解并行编程》,读者可以到RCU官方网址下载:
。
关于我们的翻译稿的详细情况,请参考链接:
关于我们与作者paul的互动情况,请参考链接:
http://blog.chinaunix.net/space.php?uid=25845340&do=blog&id=2973557
建议读者认真阅读我们翻译的《深入理解并行编程》,里面有对经典RCU、分级RCU、可抢占RCU、可睡眠RCU的详细介绍。在本博文中,我只对经典RCU作一个简要介绍,作入门用。
RCU允许多个读者和写者并发执行。它的最大的优点是:RCU并不使用其他锁。Spinlock、原子变量、信号量都是会使用“排它性装载”和“排它性存储”指令,在多核间会共享变量,这容易导致多核之间产生缓存行的乒乓效应,影响整体性能。
当然,虽然RCU有这么令人羡慕的优点,并不表示它没有缺点,否则其他锁还有存在的必要吗?
它的主要缺点是限制锁的使用范围:
ü RCU只保护被动态分配并通过指针引用的数据结构。
ü 在RCU保护的临界区中,任何代码都不能睡眠。(这是对经典RCU而言)
ü 多核之间不能看到完全一致性的数据。
RCU的读锁很简单:就是禁用和打开抢占。
相对来说,RCU的写复杂一些。当写者需要更新数据时,它生成数据结构的副本,副本修改完成后,它改变指针。因为对指针的操作是一个原子操作。所以,读写指针是安全的。尽管如此,还需要内存屏障来使用已经更新的指针对其他CPU来说是可见的。
RCU真正的难点在于:写者修改指针时,不能立即释放数据结构的旧副本,因为可能还有读者在引用指针。只有CPU上所有的读者都执行完宏rcu_read_unlock后,释放副本才是安全的。因此,内核要求:在下面操作前,必须执行rcu_read_unlock:
ü CPU执行进程切换前(因为不允许进程在获得读锁前睡眠)
ü CPU开始在用户态执行。
ü CPU执行IDLE。
以上三种状态,称为静止状态。
RCU这个新功能用在网络层和虚拟文件系统中。
1.1.2 kfifo
当只有一个读者和一个写者操作环形缓冲区时,就可以使用免锁的kfifo对象。它完全不使用任何锁。但是仍然需要使用smp_wmb来禁止可能的编译乱序,以及确保多核之间相互以正确的顺序看到写操作的结果。
当有多个读者或者写者时,需要由调用者使用其他同步手段(如自旋锁、信号量)来实现互斥。
由于没有深入研究过kfifo的实现。这里就不继续分析了。有分析过的朋友,请与我邮件联系,我的mail是:。
1.1.3 内核同步之结束语
Linux3.0终于完全摆脱了大内核锁。这真是一件值得高兴的事情。没有经受大内核锁折磨的朋友不会明白这一点。
关于大内核锁,我在工作中曾经总结了一篇文档。介绍了它的前世今生,这里不方便贴出来。有兴趣的朋友可以用google找一下相关资料。
内核同步是一个大的话题,几篇博文只是对它的一些入门介绍。大家可以再仔细阅读《深入理解LINUX内核》第三版和《深入LINUX内核架构》。相信还会有更多的收获。