[嵌入式C语言专精]侵入式链表原理及其实战

侵入式链表是什么?

链表可被分为侵入式链表与非侵入式链表

在简单的学习之中, 非侵入式的链表较为常见, 如下

struct list_example{
   
   
	int data;
    struct list_example *next;
}

链域与数据域并未进行划分, 或者说, 链域就包含于数据域之中

这样做的话其实也并没有什么坏处, 但毋庸置疑会降低代码复用

侵入式链表则是将链域与数据域区分开来, 单独为链域开辟了一个list结构体, 如下

struct list_node{
   
   
	struct list_node *prev;
    struct list_node *next;
}

typedef struct list_node list_t;

struct list_objectExample{
   
   
	//数据域
    int data;
    //链域
    list_t list;
}

可见, 将链域与数据域做了区分.

通过这种将链表孤立出来的方式, 我们可以简单地创建新的链表数据结构

侵入式链表的具体实现

侵入式链表也有显而易见的缺点, 即:

对链表进行操作时, 我们无法直接得知内部成员变量的地址偏移量, 因为链表的链域之中仅保存了前后节点的地址

因此, 要实现正常的数据读取, 增删查改等功能, 我们就要为其进行一系列的地址计算/偏移.

在linux内部, 通过两个宏函数实现了这部分的操作, 如下

/**
 * @define: container_of
 * @brief:  通过获取一个结构体的成员变量, 从而得到结构体的地址
 * @arguments:
 *  1.  __mptr(ptr): 它的类型由typeof获得, 作用是指向type结构体中成员member的一个指针
 *  2.  type:   传入结构体的模板
 *  3.  member: 传入要复制的结构体变量的成员变量名称
 * @return: 返回一个地址值
 *
 * 位于 /usr/src/include/linux/kernel.h
 */
#define container_of(ptr, type, member)({
     
      \
    const typeof ( ((type *)0)->member ) *__mptr = (ptr); \
    (type *)( (char *)__mptr - offsetof(type, member) ); \
    })

/**
 * @define: offsetof
 * @brief: 用于计算TYPE结构体中, 成员member的地址偏移量
 * @argument:
 *  1. TYPE: 传入结构体的模板
 *  2. member: 传入要复制的结构体变量的成员变量名称
 * @return: 返回偏移量的大小
 *
 * 位于 include/linux/stddef.h
 */
#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)

在本工程中, 也针对这两个宏函数进行了测试.

在这两个宏函数的作用下, 我们就可以通过链域节点的地址, 来获取到整个结构体的头地址及其内部的成员变量地址.

侵入式链表的增删查改

在这两个宏函数的辅助下, 侵入式链表的增删查改已与普通链表无异

首先, 一个链表必然要声明好链表头.
通常情况下, 链表头的链域指针可被指向自己本身, 在linux内核之中, 为了内存安全, 初始化时的链表头的链域指针指向了两个受保护的地址, 若发生了此地址的访问, 即可被归类为发生了内存错误.

/**
 * @brief: 链表头的初始化
 */
#define 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值