【Linux】list.h中链表的结构与访问方式(与双循环链表对比)

在linux内核中有一个list.h头文件。
它采用有头节点双向循环链表的方式,很优雅的支持了诸多链表操作。
本文意在辅助理解list.h中最核心的部分——内核链表如何定义 & 如何访问下一个数据。

内核链表的使用 vs 双循环链表

  • 使用双循环链表时结构体的构建:
    指针指向最外层的结构体,访问数据时访问的是结构体内部的数据元素
    使用正常结构体:指针指向最外层的结构体,访问数据时访问的是结构体内部的元素
struct Node{
	//声明一个数据 可为结构体
	struct Node *next; //指向下一个结点的指针
	struct Node *prev; //指向前一个结点的指针
}
  • 使用内核链表时,结构体的构建:
    在内核结构体外面套一层用于存储数据,
    指针指向内核结构体,访问数据时需先计算外部结构体的位置,在进行访问(详见下文)。
    在这里插入图片描述
这是list.h 中定义的一个list_head结构体,暂且称之为内核结构体。

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

内核结构体中只有两个指针,那我们在使用时,数据该如何存储呢?
显然,不能直接改动list.h中的结构体,因此我们使用时需要在内核结构体外部套一层用来存储数据(暂且称之为外部结构体)。

在使用时在内核结构体外套一层,用来存储数据
struct Node{
    int number;    想存储的数据,此处以整型为例
    struct list_head list;    list.h中定义的结构体
}

内核结构体访问数据

内核结构体访问数据时,只能找到要访问的内核结构体。

我们知道,结构体只能找到自己内部的元素。那如何找到套在外面的数据呢?

这就需要通过container_of**(ptr, type, member) (list.h提供的宏定义)来计算外部结构体位置。

找到外部结构体位置后,我们就能访问它内部的数据元素啦~

"list.h"中定义的 计算外部结构体位置的宏
#define container_of(ptr, type, member) ({			\
	const typeof(((type *)0)->member) * __mptr = (ptr);	\
	(type *)((char *)__mptr - offsetof(type, member)); })

内核结构体为啥存在

内核结构体的访问显然比常规的结构体要复杂。

但由于内核无法预先得知需要存储数据的数据结构,为保证其可扩展性,只能采用内嵌的方式。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值