2011年2月27日 星期日

Linux Modules(14.1)- Read Copy Update


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的三個階段
  1. removal:更新指標。
  2. grace period:等待所有持有舊資料的reader都離開RCU read-side。
  3. 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)。




沒有留言:

張貼留言

熱門文章