linux RCU 使用实例

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/spinlock.h>
#include <linux/rcupdate.h>
#include <linux/delay.h>
#include <linux/kthread.h> 

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
 

相关推荐

  1. linux RCU 使用实例

    2023-12-22 23:18:07       32 阅读
  2. oracle http使用实例

    2023-12-22 23:18:07       31 阅读
  3. nlohmann::json 使用实例

    2023-12-22 23:18:07       14 阅读
  4. Flink ValueStateDescriptor使用实例

    2023-12-22 23:18:07       12 阅读
  5. 使用CompletableFuture实现并发计算-结合实例

    2023-12-22 23:18:07       37 阅读
  6. 栈的实现以及使用实例 python

    2023-12-22 23:18:07       55 阅读

最近更新

  1. TCP协议是安全的吗?

    2023-12-22 23:18:07       16 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2023-12-22 23:18:07       16 阅读
  3. 【Python教程】压缩PDF文件大小

    2023-12-22 23:18:07       15 阅读
  4. 通过文章id递归查询所有评论(xml)

    2023-12-22 23:18:07       18 阅读

热门阅读

  1. 卸载anaconda报错Error: Unable to move .anaconda

    2023-12-22 23:18:07       42 阅读
  2. Halcon DL-Model相关算子

    2023-12-22 23:18:07       34 阅读
  3. MATLAB中的协方差函数

    2023-12-22 23:18:07       34 阅读
  4. 楼宇对讲门铃的芯片构成分析

    2023-12-22 23:18:07       38 阅读
  5. 代码随想录 279. 完全平方数

    2023-12-22 23:18:07       34 阅读
  6. 详解Qml的底层实现

    2023-12-22 23:18:07       33 阅读
  7. 人像美肤 人体美型 CVPR 2022 ABPN

    2023-12-22 23:18:07       38 阅读
  8. LeetCode 2866. 美丽塔 II

    2023-12-22 23:18:07       42 阅读