为什么我们需要 list_for_each_safe() 来删除内核链表中的节点? [英] Why do we need list_for_each_safe() in for deleting nodes in kernel linked list?

查看:22
本文介绍了为什么我们需要 list_for_each_safe() 来删除内核链表中的节点?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在学习如何使用来自 list.h.

I'm learning how to use the kernel linked-list API from list.h.

我了解到在使用 list_del() 删除节点时需要使用 list_for_each_safe() 而不是使用 list_for_each().

I learned that I need to use list_for_each_safe() when deleting nodes off with list_del() instead of using list_for_each().

list_for_each_safe() 的代码:

#define list_for_each_safe(pos, n, head) 
    for (pos = (head)->next, n = pos->next; pos != (head); 
        pos = n, n = pos->next)

list_for_each() 的代码:

    for (pos = (head)->next; pos != (head); pos = pos->next)

我注意到它们非常相似,除了 _safe 版本需要一个额外的参数来用作临时存储"(此处声明,list.h).

I notice they both are very similar except that the _safe version takes an extra argument to be used as 'temporary storage' (stated here, list.h).

我了解何时正确应用该函数,_safe 版本用于删除,正常版本用于访问,但我很好奇额外的参数如何使其安全"?

I understand when to apply the function correcly, _safe version for deleting, normal version for accessing, but I'm curious how the extra argument made it 'safe'?

考虑以下,我使用 list_for_each_safe() 删除链表中的每个节点:

Consider the following, where I'm deleting every node in a linked list using list_for_each_safe():

struct kool_list{
    int to;
    struct list_head list;
    int from;
    };

struct kool_list *tmp;
struct list_head *pos, *q;
struct kool_list mylist;

list_for_each_safe(pos, q, &mylist.list){
         tmp= list_entry(pos, struct kool_list, list);
         printf("freeing item to= %d from= %d
", tmp->to, tmp->from);
         list_del(pos);
         free(tmp);
    }

给出 q 对删除有什么帮助?

How does giving q help in deleting?

感谢您的帮助!

推荐答案

这是必要的,因为 list_del 在内部修改了 pos 字段的值.在您的示例中,循环体甚至释放了 pos 占用的内存.假设您将使用不安全版本的循环:

That is necessary because list_del internally modifies the value of pos fields. In your example the loop body even frees the memory occupied by pos. Suppose that you would use unsafe version of the loop:

for (pos = (head)->next; pos != (head); pos = pos->next)

执行循环体后 pos 指针变为无效,破坏增量表达式:pos = pos->next.

After executing the loop body pos pointer becomes invalid breaking the increment expression: pos = pos->next.

相反,安全的 foreach 将 pos->next 的值预先保存在一个临时变量中,然后引用后者而不是取消引用 pos:

As opposite, the safe foreach pre-saves the value of pos->next in a temporary variable and then refers to the latter instead of dereferencing pos:

for (pos = (head)->next, n = pos->next; pos != (head); 
    pos = n, n = pos->next)

这篇关于为什么我们需要 list_for_each_safe() 来删除内核链表中的节点?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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