了解 Linux 内核中的 hlist_bl_for_each_entry_rcu 宏
Understanding hlist_bl_for_each_entry_rcu macro in Linux Kernel
在浏览Linux内核源代码时,我发现hlist_bl_for_each_entry_rcu
macro.Below是它的定义
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
块。在无宏版本中,您希望每次 pos
为非 NULL 时设置 tpos
' 值,因此您将其添加到 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; })
在浏览Linux内核源代码时,我发现hlist_bl_for_each_entry_rcu
macro.Below是它的定义
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
块。在无宏版本中,您希望每次 pos
为非 NULL 时设置 tpos
' 值,因此您将其添加到 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; })