c - 理解 Linux 内核中的 hlist_bl_for_each_entry_rcu 宏

标签 c linux-kernel kernel

在浏览 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 循环中的这种情况?

最佳答案

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

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堵塞。在无宏版本中,您需要 tpos ' 每次设置的值 pos是非 NULL,因此您将其添加到 pos && 之后的循环条件中:

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

但现在 tops 非空变成了一个循环条件,所以你告诉 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; })

关于c - 理解 Linux 内核中的 hlist_bl_for_each_entry_rcu 宏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49839170/

相关文章:

将 urb 转换为 skbuff

linux-kernel - 延迟工作的 CPU 处理

c - 如何打印void * ioremap_nocache()的返回值?

c - 二进制 0000 到 FFFF 使用 C

c - 使用 SIMD,如何将 8 位掩码扩展为 16 位掩码?

c - 在 linux 内核驱动程序中向平台设备添加属性

linux - 什么linux内核代码创建了/sys/devices/system/cpu/cpuX?

c - 从内核空间声明一个指向用户空间数组的指针并填充它

C 日志库

c - 初始化结构变量时出错