一、RCU簡介
Read-Copy-Update(RCU)是一種應用在並發多線程環境下的讀寫鎖算法。相較於傳統的讀寫鎖,RCU提供了更佳的並發度,提高了讀取操作的效率,並降低了寫入操作的開銷。
在操作系統中,RCU是由Linux內核開創性地引入並應用的。自Linux 2.5起,RCU就已經在內核中得到了應用。隨着處理器核數的增加,RCU優勢已經日益顯著。
RCU實現一個簡單的思想是:讀者和寫者之間並行,讀者只需要等待寫者完成更新,而不是像傳統的讀寫鎖要求等待讀鎖或寫鎖時相互競爭。當讀者正在讀取訪問共享資源時,寫者會從舊數據開始寫入更新的數據到一個新的內存塊,而不會覆蓋舊內存塊中的數據。
二、RCU基本操作
RCU基本原理是在寫入時暫停讀取,使所有讀者可以在不安排競爭的情況下讀取共享數據。但在讀取期間執行寫操作時,需要確保讀取操作始終引用有效數據或完全忽略寫入結果,這是通過使用一組RCU API完成的。
1. rcu_read_lock()
void rcu_read_lock(void);
rcu_read_lock用於以RCU方式添加執行讀取操作所需的讀取保護。RCU讀取保護是RCU讀取地圖中的一個進程計數器,類似於Linux中遞歸讀取鎖。調用rcu_read_lock將該進程置於正在進行RCU讀取的進程列表中,並遞增RCU讀取地圖上的進程計數器。rcu_read_lock不能被遞歸調用。
2. rcu_read_unlock()
void rcu_read_unlock(void);
rcu_read_unlock在執行RCU讀操作完成後釋放RCU讀取保護。這將遞減RCU讀取地圖中的進程計數器,以指示該進程已完成RCU讀取並且已不再使用共享數據。調用rcu_read_unlock不能被忘記或遞歸調用。
三、RCU_BJ的使用
RCU_BJ是一種特定於Linux內核的RCU實現,它實現了Bhattacharya、Jonathan和Kashyap的發布機制。RCU_BJ提供RCU API,可用於控制在讀取時使用RCU;不需要任何其他鎖定機制。
1. rcu_barrier()
void rcu_barrier(void);
rcu_barrier用於確保任何RCU讀取保護都已釋放或等待。該功能等待後台工作作業完成,以確保所有之前執行的rcu_read_unlock已經完成且rcu_read_lock未再加鎖。
2. rcu_assign_pointer()
void rcu_assign_pointer(datap, ptr);
rcu_assign_pointer用於將指針分配給保護數據。此函數使指針可以通過發布以進行對此數據的訪問。它將ptr添加到RCU保護結構中,並遞增計數器,以指示ptr的替換已發布。如果在此數據的RCU保護期間發布ptr,則將其自動替換為更具體的數據。 如果在此數據的RCU保護期間發布了較舊的指針,則為了安全而不是效率原因,可以從保護期內讀取它們,但無法保證它們總是訪問有效的指向數據的指針。
3. rcu_dereference()
void *rcu_dereference(pointer);
rcu_dereference用於在RCU保護期間引用數據。如果在RCU保護期間不更改指針,則rcu_dereference返回這個指針。如果在RCU保護期間更改指針並且已發布了該更改,則返回新指針。如果在保護期間曾發布了更具體的數據,則返回該數據。
4.例子
struct my_datap { int a; int b; }; DEFINE_SPINLOCK(datap_lock); struct my_datap *data __read_mostly; void foo(void) { struct my_datap *newp = kmalloc(sizeof(*newp), GFP_KERNEL); if (!newp) return; spin_lock(&datap_lock); *newp = *data; rcu_assign_pointer(data, newp); spin_unlock(&datap_lock); kfree_rcu(data, rcu); } void bar(void) { int sum = 0; struct my_datap *dp = rcu_dereference(data); if (dp) sum = dp->a + dp->b; printk("Sum: %d\n", sum); rcu_barrier(); /*等待訪問完成*/ }
在上述示例中,foo函數用於為數據指針data分配新內存,並使用rcu_assign_pointer發布內存分配。另一方面,bar函數使用rcu_dereference用於讀取數據指針。最後,rcu_barrier用於確保RCU訪問已經完成。此時,新的數據指向新分配的內存。
原創文章,作者:ZQLGJ,如若轉載,請註明出處:https://www.506064.com/zh-hant/n/368229.html