这篇文章 What is RCU? Part 2: Usage
作者:
Paul E. McKenney, IBM Linux Technology Center ,
这篇文章主要通过与几以下几类机制的比较,深入对RCU进行了分析:
- RCU与读写锁机制;
- RCU是一种严格引用计数机制 Restricted Reference-Counting Mechanism
- RCU与GC机制;
- RCU与Existence guarantees(出自论文Gamsa等。[PDF])
- RCU是一种事件等待机制;
RCU优势:
- 性能优势:实验中与读写机制rwlock比较, 随着CPU增加RCU CPU开销没有明显增长;
- 死锁免疫(Deadlock Immunity):由于读取端没有阻塞, 理论上不会有死锁。
- 实时性、低延时:同样也是由于RCU读端的不阻塞,使他有更出色的实时性和低延时。
- RCUreader与updater同时运行
rwlock保证读者总是读到更新后的数据, 但是作者也提到了现实中类似路由表的应用, 对于旧数据影响并时不时很大,而rwlock这种机制也依赖于reader/writer优先级的设定
- 可以方便的替换rwlock
1 struct el { 1 struct el { 2 struct list_head list; 2 struct list_head list; 3 long key; 3 long key; 4 spinlock_t mutex; 4 spinlock_t mutex; 5 int data; 5 int data; 6 /* Other data fields */ 6 /* Other data fields */ 7 }; 7 }; 8 rwlock_t listmutex; 8 spinlock_t listmutex; 9 struct el head; 9 struct el head;
1 int search(long key, int *result) 1 int search(long key, int *result) 2 { 2 { 3 struct list_head *lp; 3 struct list_head *lp; 4 struct el *p; 4 struct el *p; 5 5 6 read_lock(&listmutex); 6 rcu_read_lock(); 7 list_for_each_entry(p, head, lp) { 7 list_for_each_entry_rcu(p, head, lp) { 8 if (p->key == key) { 8 if (p->key == key) { 9 *result = p->data; 9 *result = p->data; 10 read_unlock(&listmutex); 10 rcu_read_unlock(); 11 return 1; 11 return 1; 12 } 12 } 13 } 13 } 14 read_unlock(&listmutex); 14 rcu_read_unlock(); 15 return 0; 15 return 0; 16 } 16 }
1 int delete(long key) 1 int delete(long key) 2 { 2 { 3 struct el *p; 3 struct el *p; 4 4 5 write_lock(&listmutex); 5 spin_lock(&listmutex); 6 list_for_each_entry(p, head, lp) { 6 list_for_each_entry(p, head, lp) { 7 if (p->key == key) { 7 if (p->key == key) { 8 list_del(&p->list); 8 list_del_rcu(&p->list); 9 write_unlock(&listmutex); 9 spin_unlock(&listmutex); 10 synchronize_rcu(); 10 kfree(p); 11 kfree(p); 11 return 1; 12 return 1; 12 } 13 } 13 } 14 } 14 write_unlock(&listmutex); 15 spin_unlock(&listmutex); 15 return 0; 16 return 0; 16 } 17 } example taken from Wikipedia.
- 可以方便的替换rwlock
- 参考计数机制 Reference-Counting Mechanism:看上去和rwlock模式一致
1 rcu_read_lock(); /* acquire reference. */ 2 p = rcu_dereference(head); 3 /* do something with p. */ 4 rcu_read_unlock(); /* release reference. */
1 spin_lock(&mylock); 2 p = head; 3 head = NULL; 4 spin_unlock(&mylock); 5 synchronize_rcu(); /* Wait for all references to be released. */ 6 kfree(p);
但是由于要求读不阻塞, 所以在与rwlock进行性能比较时大概在4个cpu时rcu与rwlock的cpu开销已经趋于一致。
- RCU 批量参考计数机制,由于器轻量级的读取,对于大量数据结构生成锁这里还提到 SRCU
RCU的核心是提供以下功能的API:
- 对新数据一个订阅发布机制;
- 等待订阅这完成;
- 多版本的发布不破坏现有订阅进程的并发读取。
作者认为 RCU可以应用于读写锁,引用计数,存在保证 等场景。
这篇文章是发表于2007年, 在后续linux kernel实践过程中遇到了很多实际问题, RCU’s First-Ever CVE, and How I Lived to Tell the Tale 这个演讲中描述了RCU 相关结构的演进,还有详细的修复CVE列表。
Be First to Comment