解释list_for_each_entry和list_for_each_entry_safe

时间:2013-04-26 07:01:26

标签: list linux-kernel linux-device-driver

任何人都可以解释linux中list_for_each_entry和... entry_safe循环的工作原理。 就像

list_for_each_entry(type *cursor, struct list_head *list, member)

list_for_each_entry_safe(type *cursor, type *next, struct list_head *list,member)

所有这些参数的作用是什么以及它们如何用于遍历列表。

感谢ADVANCE

1 个答案:

答案 0 :(得分:17)

编辑:对不起,一定是迟到了,我犯了很多错别字。

他们很有趣! :)不同之处在于,如果在迭代列表时删除了某些内容,list_for_each_entry将会中断,而list_for_each_entry_safe则不会(当然,这会牺牲一些额外的CPU指令)。

虽然list.h中有一个单独链接的列表实现,但内核已经确定了双链表(我假设您理解)。你的清单只是:

struct list_head {
    struct list_head *next;
    struct list_head *prev;
};

请注意,相同的结构用于列表的“头部”以及每个节点。当列表为空时,头部的nextprev成员只指向头部自己。因此,迭代列表只是从头部的next成员开始并调用该节点的过程,除非它与prev的地址相同(当您停止时)。否则,您的for正文被调用,您可以使用container_of()宏来获取指向您的实际结构的指针并使用它。然后,在for的第3个字段中,我们只是移动到下一个next

编辑:哎呀,我道歉,你要求解释参数。好吧,如果我是你,我会直接检查出来,而不是采取别人的话。对于那些,我会建议Kernel API docs本身,至少存在于链表库中。我正在尝试获得一个补丁集,它也会为红黑树库添加它们,但是获取内容可能是一个很好的过程。

同样值得注意:http://kernelnewbies.org/FAQ/LinkedLists

这是一个简单的例子:

struct list_head my_actual_list;
struct my_struct {
    struct list_head node;
    /* some other members */
};

/* in a function body somewhere... */
struct list_head *i;
list_for_each(i, &my_actual_list) {
    struct my_struct *obj = list_entry(i, struct my_struct, node);
    // do something with obj
}

list_entry只是container_of

的别名

编辑#2

好的,所以在评论中回答你的问题时,我只想扩大我的答案。我真的很感激掌握这个概念的困难,因为它与C ++ STL容器,C数组等相比确实有一些奇怪的东西,但是一旦你习惯了习语,它看起来很自然。仍然在未来,我真的敦促你开始研究这些结构,功能和放大器的定义。宏自己,并试图拼凑一个理解,然后问问题。

首先,列表中的每个节点都是一个结构,其中包含struct list_head类型的成员,列表 其自身 的类型为{{ 1}}。因此,谁是容器并且在这种情况下包含谁,仅仅取决于它们的使用方式,但通常,它将以这些成员给出的名称表示。迭代器的类型是struct list_head。这是一个例子,我将替换正常功能&使用等效代码进行宏调用:

struct list_head *

Now go read! :)