RCU

来源:互联网 发布:杜兰特数据统计 编辑:程序博客网 时间:2024/04/27 17:37
定义在头文件linux/rcupdate.h中;
一、RCU原理
RCU,全名Read-Copy-Update(读-拷贝-更新);对于被RCU所保护的共享资源,读执行单元不需要获得任何锁就可以访问到它,也不需要使用原子指令,而且在除Alpha的所有架构上也不需要使用内存栅(Memory Barrier),因此不会导致锁竞争、内存延迟以及流水线停滞;不需要锁,也使得使用更加容易,因为死锁问题就不需要考虑了;
写执行单元在使用RCU来访问共享资源的时候,会首先对共享资源进行复制或克隆,得到共享资源的一个副本,然后对这个副本进行修改,最后使用一个回调机制在适当的时机把指向原来资源的指针重新指向新的已被修改的资源,这个时机就是所有引用该资源的CPU都完全退出对该共享资源的访问的时候;使用RCU机制,读执行单元没有任何同步开销,而写执行单元的同步开销则取决于它所使用的写执行单元间的同步机制;
RCU可以被看成是读写自旋锁的高性能版本,相比于读写自旋锁,RCU的优点在于既允许多个读执行单元同时访问被RCU保护的共享资源,又允许多个读执行单元和多个写执行单元同时访问被RCU保护的共享资源;
但是,RCU毕竟还是不能完全代替读写自旋锁,因为如果写操作比较多或者比较频繁的时候,对读执行单元的性能的提高不能弥补写执行单元所导致的损失;因为,使用RCU的时候,写执行单元之间的同步开销会比较大,它需要延迟对资源的释放,复制被修改的资源,它也必须使用某种锁机制来同步并行的其它写执行单元的修改操作;
1).读锁定:
rcu_read_lock();
rcu_read_lock_bh();
2).读解锁:
rcu_read_unlock();
rcu_read_unlock_bh();
其中,rcu_read_lock()和rcu_read_unlock()的本质实际上就是禁止和使能内核的抢占式调度;
RCU的使用模式:
rcu_read_lock();   //加锁
......             //临界区代码
rcu_read_unlock(); //解锁
二、同步RCU
synchronize_rcu():
该函数由RCU写执行单元调用,它将阻塞写执行单元,直到所有的读执行单元都已经完成读执行单元临界区的操作之后,写执行单元才能继续运行下去;如果有多个RCU写执行单元调用这个函数,那么它们将在一个grace period(即所有的读执行单元都已经完成对临界区的访问)之后全部被唤醒;synchronize_rcu()函数可以保证所有CPU都处理完正在运行的读执行单元临界区;
synchronize_kernel():
该函数由内核代码调用,用于等待所有CPU都处于可抢占状态,目前,其功能等同于synchronize_rcu(),但是现在已经不建议在使用了,而是使用synchronize_sched(),该函数用于等待所有CPU都处于可抢占(可被调度)状态,它能保证所有正在运行中的中断处理程序处理完毕,但是不能保证正在运行中的软中断处理程序处理完毕;
三、挂接回调
void fastcall call_rcu(struct rcu_head* head, void (*func)(struct rcu_head* rcu));
该函数把函数func挂接到RCU回调函数链上,然后立即返回;函数call_rcu()也由RCU写执行单元调用,但是它不会阻塞写执行单元,所以,它可以在中断上下文或软中断中使用;
synchronize_rcu()函数的实现实际上使用了call_rcu()函数;
void fastcall call_rcu_bh(struct rcu_head* head, void (*func)(struct rcu_head* rcu));
该函数的功能几乎与call_rcu()函数的功能完全相同了,唯一的区别就是它把软中断的完成也当做是经历一个quiescent state(静默状态),因此,如果写执行单元使用了该函数,在进程上下文的度执行单元中就必须使用rcu_read_lock_bh();
每个CPU都维护两个数据结构:rcu_data和rcu_bh_data;它们用于保存回调函数;函数call_rcu()会把回调函数注册到rcu_data中,而函数call_rcu_bh()则把回调函数注册到rcu_bh_data中,在每个数据结构上,回调函数被组织成一个链表,先注册的排在前头,后注册的排在尾部;
使用RCU的时候,读执行单元必须提供一个信号给写执行单元,以便于写执行单元能够确定资源可以被安全地释放或修改的时机;有一个专用的垃圾收集器用于探测读执行单元的信号,一旦所有的读执行单元都已经向该垃圾收集器发送信号,并告诉它们,都不再使用被RCU所保护的资源时,垃圾收集器就会自动调用回调函数,以完成最后的资源释放或修改操作;
目前,RCU的使用在内核中已经非常普遍了,内核中原先大量使用读写锁的代码都被RCU替换;RCU还可用于实现对链表、映射、hash表等的操作进行同步保护;事实上,内核中已经实现了RCU版本的链表操作函数;
0 0
原创粉丝点击