解释list_for_each_entry和list_for_each_entry_safe

任何人都可以解释在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)

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

提前致谢

最佳答案
编辑:对不起,必须迟到,我做了很多打字错误.

他们是纯粹的乐趣! :)区别在于,如果您在迭代列表时删除某些内容,list_for_each_entry将会中断,并且list_for_each_entry_safe不会(当然,以牺牲一些额外的CPU指令为代价).

内核已经确定了双重链接的列表(我假设你明白了),尽管在list.h中有一个单独的链表实现.您的列表只是:

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

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

编辑:哎呀,我道歉,你要求说明参数.嗯,如果我是你而不是采取某人的话,我会直接查出来.对于那些,我建议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类型的结构的结构,其自身的类型是struct list_head.因此,谁是集装箱,在这种情况下是谁所拥有的,只是依赖于它们的使用方式,但通常会以这些成员的名义来表达.迭代器的类型是struct list_head *.这是一个例子,我将替换正常的函数&宏调用及其等效代码:

struct my_container {
    struct list_head list;
    int some_member;
    /* etc. */
};

struct my_obj {
    struct list_head node;
    int some_member;
    /* etc. */
};

void func() {
    struct my_container container;
    struct my_obj obj1, obj2;
    struct list_head *i;

    /* INIT_LIST_HEAD(&container.list); */
    container.list.next = &container.list;
    container.list.prev = &container.list;

    /* list_add_tail(&obj1.node); */
    container.list.prev = &obj1.node;
    obj1.node.next = &container.list;
    obj1.node.prev = &container.list;
    container.list.next = &obj1.node;

    /* list_add_tail(&obj2.node); */
    container.list.prev = &obj2.node;
    obj2.node.next = &container.list;
    obj2.node.prev = &obj1.node;
    obj1.node.next = &obj2.node;

    /* list_for_each(i, &container.list) { */
    for (i = container.list.next; i != &container.list; i = i->next) {
        struct my_obj *obj = list_entry(i, struct my_obj, node);
        /* do stuff */
    }

}

Now go read! 🙂

转载注明原文:解释list_for_each_entry和list_for_each_entry_safe - 代码日志