RCU (Read-Copy Update)是kernel同步機制之一,允許多個reader在writer更新資料的同時讀取資料,reader可能讀到更新前或更新後的,但是資料內容是一致的(不是新的就是舊的,這是因為RCU利用指標的dereference和assign達成的),另外,RCU也能確保資料在read-side使用時不會將之free(下一篇介紹RCU的原理在提吧)。
這裡有一張圖用來描述RCU再經典不過了。首先,藍色的reader的開始就是rcu_read_lock(),結束就是rcu_read_unlock(),下面的removal、grace period和reclamation代表著writer的狀態,這邊只要保證讀到舊資料的reader(就是開頭落在removal的reader),都能在grace period結束之前,離開read-side就可以了,聰明的你一定可以看出在grace period開始之後的reader都是讀到新資料,所以RCU就不管他想用多久。
-
RCU的三個階段
- removal:更新指標。
- grace period:等待所有持有舊資料的reader都離開RCU read-side。
- reclamation:回收舊資料。
RCU本身就是read-write lock的一種,所以我們介紹一下RCU的reader和writer的形式。
struct foo { int x; }; static struct foo *foo = NULL; // Reader的形式 static int reader(void) { int ret; rcu_read_lock(); ret = rcu_dereference(foo)->x; rcu_read_unlock(); return ret; } // Writer的形式 static void writer(int x) { struct foo *new_foo, *old_foo = foo; // 建立新的資料內容new_foo new_foo = kmalloc(sizeof(struct foo), GFP_KERNEL); // 複製原本的內容 *new_foo = *old_foo; // 修改內容 new_foo->x = x; // removal rcu_assign_pointer(foo, new_foo); // grace period synchronize_rcu(); // reclamation: kfree(old_foo); }
synchronize_rcu()就是在等待所謂的grace period,等所有持舊資料的reader都離開RCU read-side才會往下執行kfree(old_foo)。
沒有留言:
張貼留言