读–拷贝–更新与读–修改–写
读–修改–写需要访问两次存储器,分别为读原值和写新值,在多处理器情况下,对同一个数据结构的此串操作,若不进行同步操作,可会会导致最终结果错误。
RCU
为保护在多数情况下被多个CPU读的数据结构而设计的另一种同步技术。
RCU允许多个读者和写者并发执行,且不使用锁,即不使用被所有CPU共享的锁或计数器,在这一点上与R/W锁或顺序锁相比较,RCU更具有优势。
RCU如何在不使用共享数据结构的情况下实现多CPU同步呢?关键思想包括限制RCU范围,如下:
1、RCU只保护被动态分配并通过指针引用的数据结构;
2、在被RCU保护的临界区中,任何内核控制路径不能休眠。
RCU读者工作过程:
1、执行宏rcu_read_lock()–>等同于preempt_disable,标记临界区开始
2、读者间接引用这个数据结构指针所对应的内存单元,并开始读数据;
3、读者在完成读数据之前,不能睡眠;
4、rcu_read_unlock()–>preempt_enable,标记临界区结束;
RCU写者过程:
1、copy一份间接引用的数据结构;
2、修改副本;
3、写者改变指向数据结构的指针,使其指向副本,修改指针是原子操作;
4、旧副本保留,直到所有读者完成rcu_read_unlock后,才释放旧副本;
5、内核要求所有读者在下面的操作之前执行rcu_read_unlock宏:
- CPU执行进程切换
- CPU开始在用户态执行
- CPU执行空循环;
在上述每种情况,CPU经过了静止态;
6、写者调用函数call_rcu来释放数据结构中的旧副本。当所有的CPU经过静止状态之后,call_rcu接受rcu_head描述符地址以及将要调用的回调函数地址作为参数。一旦回调被执行,它通常释放数据结构的旧副本。