RCU回顾

RCU通常被用来提供以读为主的数据结构的并发,从而读得开销是最小(通常认为读在内核和用户空间的消耗为0)。原理简单认为读的时候不保护,当读完检查版本,如果为旧版本则放弃。

RCU首先要保证能安全的浏览数据即使数据同时正在被修改,为此RCU采用发布-订阅的模式。例如初始化一个全局的NUll指针gp,gp指向malloc的一块区域并且初始化数据。

struct template{

  int a;

  int b;

  int  c;

};

strcut template *gp = NULL;

p = kmalloc(sizeof(*p),GFP_NERNEL);

p->a = 1;

p->b = 2;

p->c = 3;

gp = p;

但这样还是有问题的,如果分配gp在p初始化之前,那么同时读得话会读取未初始化的值。解决这个问题做了一个封装,rcu_assign_pointer。

将gp=p改成rcu_assign_pointer(gp,p),该函数发布新结构时,要求CPU在初始化p之后分配gp。不仅仅如此还要读要在合适的时候执行。

例如:

p = gp;

if(p != NULL){

  do_something_with(p->a,p->b,p->c);

}

尽管这段代码对错误进行排除,但在《Memory Ordering in Modern Microprocessors》提出了p->a,p->b,p->c会被提前读取的。更容易理解的是编译器造成的此值被提前读取,编译器猜想p值并获取p->a,p->b,p->c然后获取这实际的p值和guess的值进行对比。无论如何我们需要保护起来这一块,我理解就是RCU只保护被动态分配并通过指针引用的数据结构。

rcu_read_lock();

p = rcu_dereference(gp);

if(p != NUll){

 do_something_with(p->a,p->b,p->c);

}

rcu_read_unlock();

实际使用struct list_head

struct template{

 struct list_head list;

 int a;

 int b;

 int c;

};

LIST_HEAD(head);

p = kmalloc(sizeof(*p),GFP_KERNEL);

p->a = 1;

p->b =2;

p->c = 3;

list_add_rcu(&p->list,&head);




  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值