1

问题一:

在介绍RCU锁的文章中,他写了一个发布-订阅机制。但是我有一个关于rcu_assign_pointer()的问题,在这篇文章中,他说:

1 p->a = 1;
2 p->b = 2;
3 p->c = 3;
4 rcu_assign_pointer(gp, p);

rcu_assign_pointer() 将发布新结构,强制编译器和 CPU 在分配给 p 引用的字段之后执行对 gp 的分配。

但是编译器和CPU怎么知道p已经被赋值了呢?比如我只是初始化了p->a和p->b,那么编译器和CPU如何区分这两种情况呢?

situation 1:
1 p->a = 1;
2 p->b = 2;
3 p->c = 3;
4 rcu_assign_pointer(gp, p);

situation 2:
1 p->a = 1;
2 p->b = 2;
3 rcu_assign_pointer(gp, p);

问题2:

至于读端临界区,如果有连续的reader读取数据,是writer必须等待还是writer不能进行同步操作?如果是,读者会一直阅读旧版本吗?

4

1 回答 1

0

对问题 1 的回答: rcu_assign_pointer() 指示编译器不要优化机器指令,以便在实现/代码中的 rcu_assign_pointer() 语句之前对“p”字段所做的任何修改都在 CPU 管道中执行之前将“p”分配给“gp”。这确保了当“gp”被分配时,“p”的所有字段,因此现在是“gp”,开发人员选择分配的所有字段确实被分配。

为了进一步说明,请使用以下代码,其目的是将“y”返回给调用者:

void my_func(struct foo **y) { struct foo *x = malloc(sizeof (struct foo)); x->val1 = 1; *y = x; x->val2 = 2; return; }

开发人员并不真正关心上述赋值语句的顺序,因为他/她的意图是简单地返回填充 2 个值的 *y。因此,给定上述代码,编译器可以选择在 CPU 管道中并行执行 3 个赋值语句,并且不会破坏正确性。

现在,如果您在执行 rcu 类型的工作时使用类似的赋值语句,编译器可能会选择执行相同类型的优化,因此读者可能会得到“部分初始化”的“gp”。rcu_assign_pointer() 确保保持分配的顺序,以便开发人员在初始化所有 p 的字段后将 'p' 分配给 'gp' 的意图得以保留。

希望这应该说明,如果您,开发人员,在将 'p' 分配给 'gp' 之前选择仅分配 p->a 和 p->b,而不分配 p->c,那么这就是 gp 将得到的 - a部分初始化的结构。

对问题2的回答:

于 2015-09-12T01:45:02.787 回答