linux RCU 使用实例

#include
#include
#include
#include
#include
#include
#include
#include  

struct foo {
    int a;
    struct rcu_head rcu;
};

static struct foo *g_ptr;

static int myrcu_reader_thread(void *data)//读者线程
{
    struct foo *p = NULL;
    
    while(1) {
        //msleep(200);
        mdelay(200); //不可抢占RCU中读者获取锁不允许睡眠
        rcu_read_lock();
        p = rcu_dereference(g_ptr);
        if (p)
            printk("%s: read a=%d\n", __func__, p->a);
        rcu_read_unlock();
    }
    
    return 0;
}

static void myrcu_del(struct rcu_head *rh)
{
    struct foo *p = container_of(rh, struct foo, rcu);
    printk("%s: del a=%d\n", __func__, p->a);
    kfree(p);
}

static int myrcu_writer_thread(void *p) //写者线程
{
    struct foo *old;
    struct foo *new_ptr;
    int value = (unsigned long)p;
    
    while (1) {
        msleep(400);
        new_ptr = kmalloc(sizeof(struct foo), GFP_KERNEL);
        old = g_ptr;
        printk("%s: write to new %d\n", __func__, value);
        *new_ptr = *old;
        new_ptr->a = value;
        rcu_assign_pointer(g_ptr, new_ptr);
        call_rcu(&old->rcu, myrcu_del);
        value++;
    }
    
    return 0;
}

static int __init my_test_init(void)
{
    struct task_struct *reader_thread;
    struct task_struct *writer_thread;
    
    int value = 5;
    printk("figo: my module init");
    g_ptr = kzalloc(sizeof(struct foo), GFP_KERNEL);
    
    reader_thread = kthread_run(myrcu_reader_thread,NULL,"rcu_reader");
    writer_thread = kthread_run(myrcu_writer_thread,(void *)(unsigned long)value,"rcu_writer");
    return 0;
}
static void __exit my_test_exit(void)
{
    printk("goodbye\n");
    if (g_ptr)
        kfree(g_ptr);
}
MODULE_LICENSE("GPL");
module_init(my_test_init);
module_exit(my_test_exit);

对于读者线程myrcu_reader_thread:
1)    通过rcu_read_lock()和rcu_read_unlock()来构建一个读者的临界区。
2)    通过调用rcu_dereference()获取被保护数据g_ptr指针的一个副本,即指针p,这时p和g_ptr都指向旧的被保护数据。
3)    读者线程每隔200毫秒读取一次被保护数据。

对于写者线程myrcu_writer_thread:
1)    分配一个新的保护数据new_ptr,并修改相应的数据。
2)    rcu_assign_pointer()让g_ptr指向新数据。
3)    call_rcu()注册一个回调函数,确保所有对旧数据的引用都执行完成之后,才调用回调函数来删除旧数据old_data.
4)    写者线程每隔400毫秒修改被保护数据。

输出:
[162809.226469] figo: my module init
[162809.441385] myrcu_reader_thread: read a=0
[162809.644025] myrcu_writer_thread: write to new 5
[162809.648888] myrcu_reader_thread: read a=5
[162809.660006] myrcu_del: del a=0
[162809.846702] myrcu_reader_thread: read a=5
[162810.049708] myrcu_writer_thread: write to new 6
[162810.053969] myrcu_reader_thread: read a=6
[162810.080608] myrcu_del: del a=5
[162810.270821] myrcu_reader_thread: read a=6
[162810.454659] myrcu_writer_thread: write to new 7
[162810.486279] myrcu_del: del a=6
[162810.488527] myrcu_reader_thread: read a=7
[162810.692156] myrcu_reader_thread: read a=7
[162810.865196] myrcu_writer_thread: write to new 8
[162810.881099] myrcu_del: del a=7
 

你可能感兴趣的:(linux,linux,c语言,网络)