欢迎来到天天文库
浏览记录
ID:19335732
大小:58.50 KB
页数:16页
时间:2018-10-01
《linux_rcu机制详解》由会员上传分享,免费在线阅读,更多相关内容在应用文档-天天文库。
1、一:前言RCU机制出现的比较早,只是在linuxkernel中一直到2.5版本的时候才被采用.关于RCU机制,这里就不做过多的介绍了,网上有很多有关RCU介绍和使用的文档.请自行查阅.本文主要是从linuxkernel源代码的角度.来分析RCU的实现.在讨论RCU的实现之前.有必要重申以下几点:1:RCU使用在读者多而写者少的情况.RCU和读写锁相似.但RCU的读者占锁没有任何的系统开销.写者与写写者之间必须要保持同步,且写者必须要等它之前的读者全部都退出之后才能释放之前的资源.2:RCU保护的是指针.这一点尤其重要.因为指针赋值是一条单指令.也就是说是一个原子操作.因它更改指针
2、指向没必要考虑它的同步.只需要考虑cache的影响.3:读者是可以嵌套的.也就是说rcu_read_lock()可以嵌套调用.4:读者在持有rcu_read_lock()的时候,不能发生进程上下文切换.否则,因为写者需要要等待读者完成,写者进程也会一直被阻塞.以下的代码是基于linuxkernel2.6.26二:使用RCU的实例Linuxkernel中自己附带有详细的文档来介绍RCU,这些文档位于linux-2.6.26.3/Documentation/RCU.这些文档值得多花点时间去仔细研读一下.下面以whatisRCU.txt中的例子作为今天分析的起点:structfoo{
3、 inta; charb; longc;};DEFINE_SPINLOCK(foo_mutex);structfoo*gbl_foo;voidfoo_update_a(intnew_a){ structfoo*new_fp; structfoo*old_fp; new_fp=kmalloc(sizeof(*new_fp),GFP_KERNEL); spin_lock(&foo_mutex); old_fp=gbl_foo; *new_fp=*old_fp; new_fp->a=new
4、_a; rcu_assign_pointer(gbl_foo,new_fp); spin_unlock(&foo_mutex); synchronize_rcu(); kfree(old_fp);}intfoo_get_a(void){ intretval; rcu_read_lock(); retval=rcu_dereference(gbl_foo)->a; rcu_read_unlock(); returnretval;}如上代码所示,RCU被用来保护全局指针structfoo*gbl
5、_foo.foo_get_a()用来从RCU保护的结构中取得gbl_foo的值.而foo_update_a()用来更新被RCU保护的gbl_foo的值.另外,我们思考一下,为什么要在foo_update_a()中使用自旋锁foo_mutex呢?假设中间没有使用自旋锁.那foo_update_a()的代码如下:voidfoo_update_a(intnew_a){ structfoo*new_fp; structfoo*old_fp; new_fp=kmalloc(sizeof(*new_fp),GFP_KERNEL); old_
6、fp=gbl_foo; 1:------------------------- *new_fp=*old_fp; new_fp->a=new_a; rcu_assign_pointer(gbl_foo,new_fp); synchronize_rcu(); kfree(old_fp);}假设A进程在上图----标识处被B进程抢点.B进程也执行了goo_ipdate_a().等B执行完后,再切换回A进程.此时,A进程所持的old_fd实际上已经被B进程给释放掉了.此后A进程对old_fd的操作都是非法的
7、.另外,我们在上面也看到了几个有关RCU的核心API.它们为别是:rcu_read_lock()rcu_read_unlock()synchronize_rcu()rcu_assign_pointer()rcu_dereference()其中,rcu_read_lock()和rcu_read_unlock()用来保持一个读者的RCU临界区.在该临界区内不允许发生上下文切换.rcu_dereference():读者调用它来获得一个被RCU保护的指针.Rcu_assign_point
此文档下载收益归作者所有