说明list_for_each_entry和list_for_each_entry_safe [英] Explain list_for_each_entry and list_for_each_entry_safe

查看:1099
本文介绍了说明list_for_each_entry和list_for_each_entry_safe的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

谁能解释Linux中list_for_each_entry和... entry_safe循环的工作. 就像

Can anyone explain the working of list_for_each_entry and ...entry_safe loop in linux. It is like

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)

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

What are the role of all these parameters and how they are used to traverse the list.

非常感谢

推荐答案

对不起,一定要迟到了,我犯了很多错字.

sorry, it must be late, I've made a lot of typos.

它们真有趣! :)区别在于,如果在迭代列表时删除某些内容,list_for_each_entry将会中断,而list_for_each_entry_safe不会中断(当然,这要花一些额外的CPU指令).

They are pure fun! :) The difference is that list_for_each_entry will break if you delete something while iterating the list and list_for_each_entry_safe won't (of course, at the expense of some extra CPU instructions).

尽管list.h中有一个严格的链表实现,但内核已经确定了双链表(我想您理解了).您的清单是:

The kernel has settled on doubly-linked lists (which I'm presuming you understand), although there is a singingly linked list implementation in list.h. Your list is just:

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

请注意,列表的头"和每个节点都使用相同的结构.当列表为空时,标头的nextprev成员仅指向标头自身.因此,迭代列表只是从头的next成员开始并调用该节点的过程,除非它与prev是相同的地址(停止时).否则,将调用for主体,并且可以使用container_of()宏获取指向实际结构的指针并对其进行处理.然后,在for的第3个字段中,我们只是移至下一个next.

Note that the same struct is used for both the "head" of the list as well as each node. When the list is empty, the head's next and prev members just point to the head its self. Thus, iterating the list is just a process of starting with the head's next member and calling that a node, unless it's the same address as prev (when you stop). Otherwise, your for body is invoked and you can use the container_of() macro to get a pointer to your actual struct and play with it. Then, in the 3rd field of the for, we just just move to the next next.

抱歉,您要求提供有关参数的说明.好吧,如果我是您,我会直接检查出来,而不是相信别人.对于这些,我建议自己使用内核API文档 ,至少在链表列表库中存在.我正在尝试获得一个补丁集,该补丁集也将它们添加到红黑树库中,但是要完成任务可能是一个相当大的过程.

whoops, I apologize, you asked for an explanation of the parameters. Well, I would check it out directly if I were you rather than taking somebody's word for it. For those, I would suggest the Kernel API docs themselves, which at least exist for the linked list library. I'm trying to get a patch set through that will add them for the red-black tree library as well, but getting stuff through can be quite a process.

还要注意: 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数组等相比,它确实有一些奇怪的东西,但是一旦您习惯了这些习惯用法,它就会显得很自然.仍然在将来,我真的敦促您开始研究这些结构,功能和功能的定义.自己建立宏并尝试加深理解,然后提出问题.

OK, so in answer to your question in comments, I'm going to just expand my answer. I can actually appreciate the difficulty in grasping this concept as it does have a few strange things in it compared to C++ STL containers, C arrays, etc, but once you are accustom to the idioms, it will seem quite natural. Still in the future, I really urge you to start looking at the definition for these structs, functions & macros yourself and trying to piece together an understanding, then ask the questions.

因此,首先,列表中的每个节点都是一个结构,其中包含类型为struct list_head的成员,列表 其自身 的类型为struct list_head.因此,在这种情况下,谁是容器,谁是容器,仅取决于如何使用它们,但是通常,将使用给定这些成员的名称来表示它.迭代器的类型为struct list_head *.这是一个示例,我将替换常规功能&宏调用及其等效代码:

So first off, each node in your list is a struct that contains a member of type struct list_head and the list its self is of type struct list_head. Thus, who is the container and who is the contained in this case, simply depends upon how they are used, but typically, it will be expressed in the names these members are given. The type of the iterator is struct list_head *. Here's an example and I'll replace the normal function & macro calls with their equivalent code:

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 */
    }

}

现在开始阅读! :)

这篇关于说明list_for_each_entry和list_for_each_entry_safe的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆