linux内核之双向链表实现原理

1. 内核中双向链表结构

Linux内核中广泛使用了一种称为循环双链(Circular Doubly Linked)链表的数据结构,即每个节点都有一个向前和向后的链接,而且首尾节点也相互连接。使用这样的链表,你可以很方便地访问任何一个元素的上一个和下一个元素,且无论目前位于哪个元素。

循环双链表的节点通常用struct list_head结构来表示,其定义如下:

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

其中,next指向链表中的下一个元素,prev指向上一个元素。

要在你自己的结构中使用链表,通常在你的结构体中包含一个struct list_head类型的变量。例如:

struct my_struct {
    int my_number;

    // 这是一个链表节点,将用于将你的结构链接到链表中
    struct list_head list_node;
}

ps:本质就是在自己定义的结构体中嵌入一个struct list_head类型的变量,注意这里不是嵌入结构体指针,而是嵌入结构体本身; 还有这个自己定义的结构体并不是说用户程序定义的,既然是给内核使用的,那必然是内核程序定义的,或者内核代码定义的。

这样,就可以使用Linux内核提供的链表函数,例如 list_add()(在链表中添加新节点)、list_del()(删除节点)、list_empty()(检查链表是否为空)等,来操作链表。

注意:在你的代码中,通常不直接操作nextprev指针。相反,你应当使用内核提供的链表函数,因为这些函数已经对各种边缘情况进行了处理,可以确保你的链表操作是正确且安全的。

举例说明

假设你的数据结构如下:

struct my_struct {
    int value;
    struct list_head list_node;
};

在这种情况下,你可以使用如下方式将自定义数据结构添加到链表中:

struct my_struct item1;
INIT_LIST_HEAD(&item1.list_node);

...

struct my_struct item2;
list_add(&item2.list_node, &item1.list_node);

这里,list_additem2list_node加入到item1list_node后面。当然,list_add函数其实只关心list_node部分,它不知道这个节点是与什么类型的数据结构关联。

你可能会问:那么当我从链表中获取一个节点时,我如何找回它所关联的数据结构呢?

答案是:使用list_entry宏。例如:

struct list_head *ptr = ...;  // 假设指向你想要的链表节点
struct my_struct *entry = list_entry(ptr, struct my_struct, list_node);

这里,list_entry宏将指针从list_node成员转换为包含它的整个结构体。这个转换是通过计算偏移量完成的。list_entry需要你提供链表节点的指针、包含该节点的数据结构的类型、以及链表节点在该结构体中的名称。结果是一个指向整个数据结构的指针。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值