看了一堆RCU的文檔,總結一下,這玩意兒實際編程用得不多,權當自娛自樂
https://www.ibm.com/developerworks/cn/linux/l-rcu/
LDD3rd中 linux同步機制 章節有對RCU比較透徹的介紹
http://hi.baidu.com/j_fo/blog/item/6e7f74c60711381d9c163df2.html
http://www.rdrop.com/users/paulmck/rclock/
http://lse.sourceforge.net/locking/rcupdate.html
http://lwn.net/Articles/262464/
http://lwn.net/Articles/263130/
http://lwn.net/Articles/264090/
RCU的原理總結如下:
RCU(Read-Copy Update),顧名思義就是讀-拷貝修改,它是基於其原理命名的。對於被RCU保護的共用資料結構,讀者不需要獲得任何鎖就可以訪問它,但寫者在訪問它時首先拷貝一個副本,然後對副本進行修改,最後使用一個回調(callback)機制在適當的時機把指向原來資料的指標重新指向新的被修改的資料。這個時機就是所有引用該資料的CPU都退出對共用資料的操作。
因此RCU實際上是一種改進的rwlock,讀者幾乎沒有什麼同步開銷,它不需要鎖,不使用原子指令,而且在除alpha的所有架構上也不需要記憶體柵(Memory Barrier),因此不會導致鎖競爭,記憶體延遲以及流水線停滯。不需要鎖也使得使用更容易,因為死結問題就不需要考慮了。寫者的同步開銷比較大,它需要延遲資料結構的釋放,複製被修改的資料結構,它也必須使用某種鎖機制同步並行的其它寫者的修改操作。讀者必須提供一個訊號給寫者以便寫者能夠確定資料可以被安全地釋放或修改的時機。有一個專門的垃圾收集器來探測讀者的訊號,一旦所有的讀者都已經發送訊號告知它們都不在使用被RCU保護的資料結構,垃圾收集器就調用回呼函數完成最後的資料釋放或修改操作。
RCU與rwlock的不同之處是:它既允許多個讀者同時訪問被保護的資料,又允許多個讀者和多個寫者同時訪問被保護的資料(注意:是否可以有多個寫者並行訪問取決於寫者之間使用的同步機制),讀者沒有任何同步開銷,而寫者的同步開銷則取決於使用的寫者間同步機制。但RCU不能替代rwlock,因為如果寫比較多時,對讀者的效能提高不能彌補寫者導致的損失。
讀者在訪問被RCU保護的共用資料期間不能被阻塞,這是RCU機製得以實現的一個基本前提,也就說當讀者在引用被RCU保護的共用資料期間,讀者所在的CPU不能發生環境切換,spinlock和rwlock都需要這樣的前提。寫者在訪問被RCU保護的共用資料時不需要和讀者競爭任何鎖,只有在有多於一個寫者的情況下需要獲得某種鎖以與其他寫者同步。寫者修改資料前首先拷貝一個被修改元素的副本,然後在副本上進行修改,修改完畢後它向記憶體回收行程註冊一個回呼函數以便在適當的時機執行真正的修改操作。等待適當時機的這一時期稱為grace
period,而CPU發生了環境切換稱為經曆一個quiescent state,grace period就是所有CPU都經曆一次quiescent state所需要的等待的時間。垃圾收集器就是在grace period之後調用寫者註冊的回呼函數來完成真正的資料修改或資料釋放操作的。
讀取者在訪問RCU被保護的共用資料期間不能被阻塞這點很重要,這保證了這段讀取代碼是原子的,只要讀取者relinquish了CPU,這次動作的在當前CPU上引用計數就為0,下一次再進入的話需要繼續調用rcu_read_lock/rcu_read_unlock。因此只要所有的CPU都被調度一次,這時就可以保證被RCU保護的共用資料不會再有讀引用計數,此時寫操作就可以釋放空間了,一般就是調一個kfree完事。
如何調用在實際情境中使用RCU本文沒有提及,目前對於鏈表操作提供了一些宏,至於其他資料結構,請參考相關文檔