为什么内核中的大多数链表循环宏都会跳过第一个元素?

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 elementhead->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 devicemsi_list 字段,而其他元素每个 list struct msi_desc 的元素。当迭代列表时,我们只想迭代 struct msi_desc 数据元素(我们已经有了 struct device - 这就是我们首先获得列表头部的方式)。