linux 内核机制--链表机制(三):list_for_each_entry_safe

目录

宏定义

工作原理

示例代码

注意事项

总结


list_for_each_entry_safe 是 Linux 内核中用于遍历链表的一个宏,特别适用于在遍历过程中可能需要删除当前节点的情况。它通过使用两个指针来确保即使在删除当前节点时,遍历过程也不会被打断。

宏定义

 

c

深色版本

#define list_for_each_entry_safe(pos, n, head, member)              \
    for (pos = list_first_entry(head, typeof(*pos), member),        \
         n = list_next_entry(pos, member);                          \
         &pos->member != (head);                                    \
         pos = n, n = list_next_entry(n, member))
  • 参数:
    • pos: 当前正在访问的链表元素。
    • n: 下一个链表元素,用于防止在删除当前节点时导致遍历中断。
    • head: 链表头指针。
    • member: 结构体中链表节点的名字。

工作原理

list_for_each_entry_safe 主要解决了在遍历过程中删除节点可能导致的问题。例如,如果你直接使用 list_for_each_entry 来遍历链表,并且在遍历过程中删除了当前节点,那么下一次循环时由于当前节点已经被移除,可能会导致未定义行为或崩溃。

为了避免这种情况,list_for_each_entry_safe 使用了一个额外的指针 n 来保存下一个节点的位置,这样即使当前节点被删除,我们仍然知道下一个要访问的节点是谁。

示例代码

假设你有一个结构体和一个链表:

 

c

深色版本

struct my_struct {
    int data;
    struct list_head list; // 嵌入到结构体中的链表节点
};

LIST_HEAD(my_list); // 初始化一个空链表头

现在,让我们看一个如何使用 list_for_each_entry_safe 的例子,其中我们将遍历链表并删除所有 data 等于某个特定值的节点:

 

c

深色版本

void remove_entries(struct list_head *head, int value_to_remove)
{
    struct my_struct *pos, *tmp;

    list_for_each_entry_safe(pos, tmp, head, list) {
        if (pos->data == value_to_remove) {
            list_del(&pos->list); // 删除当前节点
            kfree(pos);           // 释放内存(如果适用)
        }
    }
}

在这个例子中:

  1. pos 是当前遍历到的链表元素。
  2. tmp 是指向下一个链表元素的指针,这样即使我们删除了 pos,仍然可以安全地继续遍历。
  3. 如果 pos->data 等于我们要删除的值,我们就调用 list_del() 删除该节点,并调用 kfree() 释放内存(如果该结构体是动态分配的)。

注意事项

  1. 类型推导typeof(*pos) 自动推导出 pos 指向的结构体类型。这使得代码更加简洁,但需要注意确保 pos 类型正确。
  2. 成员名member 参数是指向嵌入在结构体中的 struct list_head 成员的名字。确保这个名称与结构体定义中的实际成员名称一致。
  3. 性能: 虽然 list_for_each_entry_safe 提供了安全性,但它也引入了一些额外的开销,因为需要维护第二个指针 n。因此,在不需要删除节点的情况下,推荐使用更高效的 list_for_each_entry

总结

list_for_each_entry_safe 是一个强大的工具,特别适合那些在遍历过程中可能需要修改链表(如删除节点)的场景。通过预先保存下一个节点的位置,它可以保证遍历过程不会因链表结构的变化而中断。然而,对于仅需读取链表内容而不修改链表结构的场景,使用 list_for_each_entry 可能会更高效。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小蘑菇二号

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值