RCU

定義在頭文件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版本的鏈表操作函數;
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章