I'm*_*gon 12 c foreach kernel linked-list linux-kernel
我正在学习如何使用list.h中的内核链表API .
我了解到我需要list_for_each_safe()在删除节点时使用list_del()而不是使用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).
我知道什么时候应用函数correcly,_safe版本删除,正常版本访问,但我很好奇额外的论点如何使它"安全"?
请考虑以下内容,我将删除链接列表中的每个节点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\n", tmp->to, tmp->from);
         list_del(pos);
         free(tmp);
    }
如何q帮助删除?
谢谢你的帮助!
Eld*_*mov 22
这是必要的,因为list_del内部修改了pos字段的值.在你的例子中,循环体甚至释放了占用的内存pos.假设您将使用不安全版本的循环:
for (pos = (head)->next; pos != (head); pos = pos->next)
执行循环体pos指针后变为无效,打破增量表达式:pos = pos->next.
相反,安全foreach预先保存pos->next临时变量的值,然后引用后者而不是解除引用pos:
for (pos = (head)->next, n = pos->next; pos != (head); \
    pos = n, n = pos->next)