为什么内核中的大多数链表循环宏都会跳过第一个元素?
Why do most linked list looping macros in the kernel skip the first element?
我可能是错的,但继续查看 <linux/list.h>
中的代码,我看到像 list_for_each_entry_safe 这样的宏从第二个元素开始:
#define list_for_each_entry_safe(pos, n, head, member) \
for (pos = list_entry((head)->next, typeof(*pos), member), \
n = list_entry(pos->member.next, typeof(*pos), member); \
&pos->member != (head); \
pos = n, n = list_entry(n->member.next, typeof(*n), member))
注意循环以 pos = list_entry((head)->next
.
开始
我知道这听起来可能有点挑剔,但在 "true" foreach 中,例如 Python 你从第一个或第 0 个元素开始。
是否有任何特殊原因导致内核违反此约定? 是性能原因吗?
或者我对上面代码的理解完全错误?
head
是列表本身的 head,而不是列表的 first element。 head->next
实际上是一种引用列表第一个元素的方法。
例如,下面是 returns 列表第一个条目的宏定义:
#define list_first_entry(ptr, type, member) \
list_entry((ptr)->next, type, member)
内核的列表类型是一种侵入式数据结构,其中列表元素结构包含在列表的数据元素中,而不是包含数据的外部列表列表元素中的元素(或指向它们的指针)。
但是,列表的第一个(头)元素不包含在数据元素中。相反,它包含在拥有列表的数据结构中(这可能与数据元素的类型不同)。这意味着当遍历列表的数据元素时,您不包括列表头(因为它根本不包含在数据元素中)。
例如,struct device
(在 linux/device.h
中定义)包含字段 struct list_head msi_list;
。这是struct msi_desc
列表的头部(在linux/msi.h
中定义),struct msi_desc
包含一个对应的字段struct list_head list;
。 MSI 描述符列表由 struct list_head
个元素的链表组成,但头元素是 struct device
的 msi_list
字段,而其他元素每个 list
struct msi_desc
的元素。当迭代列表时,我们只想迭代 struct msi_desc
数据元素(我们已经有了 struct device
- 这就是我们首先获得列表头部的方式)。
我可能是错的,但继续查看 <linux/list.h>
中的代码,我看到像 list_for_each_entry_safe 这样的宏从第二个元素开始:
#define list_for_each_entry_safe(pos, n, head, member) \
for (pos = list_entry((head)->next, typeof(*pos), member), \
n = list_entry(pos->member.next, typeof(*pos), member); \
&pos->member != (head); \
pos = n, n = list_entry(n->member.next, typeof(*n), member))
注意循环以 pos = list_entry((head)->next
.
我知道这听起来可能有点挑剔,但在 "true" foreach 中,例如 Python 你从第一个或第 0 个元素开始。
是否有任何特殊原因导致内核违反此约定? 是性能原因吗?
或者我对上面代码的理解完全错误?
head
是列表本身的 head,而不是列表的 first element。 head->next
实际上是一种引用列表第一个元素的方法。
例如,下面是 returns 列表第一个条目的宏定义:
#define list_first_entry(ptr, type, member) \
list_entry((ptr)->next, type, member)
内核的列表类型是一种侵入式数据结构,其中列表元素结构包含在列表的数据元素中,而不是包含数据的外部列表列表元素中的元素(或指向它们的指针)。
但是,列表的第一个(头)元素不包含在数据元素中。相反,它包含在拥有列表的数据结构中(这可能与数据元素的类型不同)。这意味着当遍历列表的数据元素时,您不包括列表头(因为它根本不包含在数据元素中)。
例如,struct device
(在 linux/device.h
中定义)包含字段 struct list_head msi_list;
。这是struct msi_desc
列表的头部(在linux/msi.h
中定义),struct msi_desc
包含一个对应的字段struct list_head list;
。 MSI 描述符列表由 struct list_head
个元素的链表组成,但头元素是 struct device
的 msi_list
字段,而其他元素每个 list
struct msi_desc
的元素。当迭代列表时,我们只想迭代 struct msi_desc
数据元素(我们已经有了 struct device
- 这就是我们首先获得列表头部的方式)。