【问题标题】:Understanding hlist_bl_for_each_entry_rcu macro in Linux Kernel理解 Linux 内核中的 hlist_bl_for_each_entry_rcu 宏
【发布时间】:2018-04-15 06:38:44
【问题描述】:

在浏览Linux内核源码时,我发现hlist_bl_for_each_entry_rcu宏。下面是它的定义

for (pos = hlist_bl_first_rcu(head);                            \
                pos &&                                                  \
                ({ tpos = hlist_bl_entry(pos, typeof(*tpos), member); 1; }); \
                pos = rcu_dereference_raw(pos->next))

此宏用于__d_lookup() 获取dentry。我不明白的是这条线

({ tpos = hlist_bl_entry(pos, typeof(*tpos), member); 1; });

它获得了 tpos。 1 在这里有什么用?在for循环中如何理解这个条件?

【问题讨论】:

  • 该行使用GCC extension known as a statement expression。将该行视为一个函数,其返回值始终为1
  • @user3386109- 这意味着 for 循环中的条件是“pos && 1”,而与 tpos 的值无关?
  • 是的。由于short-circuit evaluationtpos 只会在pos 不为 NULL 时更新。当pos 不为NULL 时,循环体将始终 执行。循环条件不检查 tpos 是否为 NULL。要么保证tpospos 不为NULL 时始终有效,要么循环体需要处理tpos 为NULL 的情况。

标签: c linux-kernel kernel


【解决方案1】:

如果你写的是无宏的,它可能看起来像这样:

for (pos = hlist_bl_first_rcu(head); pos; pos = rcu_dereference_raw(pos->next)) {
    tpos = hlist_bl_entry(pos, typeof(*tpos), member);

    /* do something with pos and tpos */

}

对于宏,您可能希望将tpos = hlist_bl_entry(pos, typeof(*tpos), member); 移动到for (...),因此用户只需提供for 块。在无宏版本中,您希望每次pos 为非NULL 时都设置tpos' 值,因此您将其添加到pos && 之后的循环条件中:

pos && (tpos = hlist_bl_entry(pos, typeof(*tpos), member))

但现在 top 非空变成了一个循环条件,所以你告诉 C 给ignore the return value

pos && ((tpos = hlist_bl_entry(pos, typeof(*tpos), member)), 1)

但是内核代码无论如何都是 GNU C,所以你可以使用 statement expressions 代替:

pos && ({ tpos = hlist_bl_entry(pos, typeof(*tpos), member); 1; })

【讨论】:

    猜你喜欢
    • 2013-03-27
    • 2011-12-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-03-02
    • 1970-01-01
    • 2021-12-30
    相关资源
    最近更新 更多