侵入式链表是什么?
链表可被分为侵入式链表与非侵入式链表
在简单的学习之中, 非侵入式的链表较为常见, 如下
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

最低0.47元/天 解锁文章
179

被折叠的 条评论
为什么被折叠?



