linux kernel 中的链表(二)
来源:互联网 发布:网络主播小宝 编辑:程序博客网 时间:2024/05/16 19:35
linux kernel 中的链表(二)
hlist 的定义
前文提到的 linux/list.h
,这个文件中实际包含了一个双向链表和一个哈希头,哈希链表的定义如下:
struct hlist_head { struct hlist_node *first;};struct hlist_node { struct hlist_node *next, **pprev;};
hlist_head 是哈希头结点,里面只有一个指向链表结构的指针,表示哈希头下的第一个元素。
hlist_node 中有两个指针,next 指针比较好理解,就是指向下一个链表元素,但是 pprev 则比较难理解一点。
pprev 在使用中,是指向上一个结点的 next 指针(即指向指针的指针变量)。这样做的好处主要是为了保证结构体的通用性。如下所示:
hlist_head1 是一个哈希表数组,为了解决冲突,在数组中都会有一个 first 的指针,从它开始挂载各个冲突到同一个哈希值的元素。那么为了定义这些挂载的哈希元素,首先需要 next 指针做串联,然后需要一个 prev 指向他的前驱节点。那么问题来了,第一个挂载的元素,他的前驱节点是 hlist_head 和其他的节点的头不一致。为了解决这个问题,所有的 hlist_node 的前驱节点修改为 hlist_node **pprev
,这样第一个节点也能赋值 pprev = &head->first 。
hlist 的基础操作
类似于普通的链表,hlist 也提供诸如新增,删除等操作,具体如下:
/* * 判断类型函数 */static inline int hlist_unhashed(const struct hlist_node *h) // 判断一个元素是否未在哈希表里{ return !h->pprev;}static inline int hlist_empty(const struct hlist_head *h) // 判断一个哈希桶下是否为空{ return !h->first;}/* * 基础操作 */static inline void hlist_del_init(struct hlist_node *n); // 从hlist中删除一个节点,并初始化它static inline void hlist_del(struct hlist_node *n);static inline void hlist_add_head(struct hlist_node *n, struct hlist_head *h);static inline void hlist_add_before(struct hlist_node *n, struct hlist_node *next);static inline void hlist_add_after(struct hlist_node *n, struct hlist_node *next);static inline void hlist_move_list(struct hlist_head *old, struct hlist_head *new);// 以上是一些顾名思义的操作了,包括删除节点,从头新增,在某个节点前新增,在某个节点后新增,移动一个节点
以其中删除节点为例子进行分析:
/* * 这里的*pprev = next;体现出了 struct 中的设计的优越性 * 一句话屏蔽了对于前驱节点的判断,因为 head 和 node 的下一个节点的指针类型都是 hlist_node */static inline void __hlist_del(struct hlist_node *n){ struct hlist_node *next = n->next; struct hlist_node **pprev = n->pprev; *pprev = next; //前驱节点的下一个节点修改为后继节点 if (next) next->pprev = pprev; //后继节点的上一个节点修改为前驱节点}static inline void hlist_del(struct hlist_node *n){ __hlist_del(n); n->next = LIST_POISON1; n->pprev = LIST_POISON2;}
这里有两个宏定义:
poison.h:#define LIST_POISON1 ((void *) 0x00100100 + POISON_POINTER_DELTA)poison.h:#define LIST_POISON2 ((void *) 0x00200200 + POISON_POINTER_DELTA)
只是一个访问之后会引起页错误的特殊地址,以下为.h里的原文:
/* * These are non-NULL pointers that will result in page faults * under normal circumstances, used to verify that nobody uses * non-initialized list entries. */
常用宏
hlist 中的宏和 list 基本是一样的,也是包括初始化和枚举:
初始化:
#define HLIST_HEAD_INIT { .first = NULL }#define HLIST_HEAD(name) struct hlist_head name = { .first = NULL }#define INIT_HLIST_HEAD(ptr) ((ptr)->first = NULL)
枚举宏:
#define hlist_entry(ptr, type, member) container_of(ptr,type,member)/** * hlist_for_each_entry_safe - iterate over list of given type safe against removal of list entry * @tpos: the type * to use as a loop cursor. * @pos: the &struct hlist_node to use as a loop cursor. * @n: another &struct hlist_node to use as temporary storage * @head: the head for your list. * @member: the name of the hlist_node within the struct. */#define hlist_for_each_entry_safe(tpos, pos, n, head, member) \ for (pos = (head)->first; \ pos && ({ n = pos->next; 1; }) && \ ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \ pos = n)
这里的 tpos 是指自己的外包 struct 指针,pos 是用来循环的当前 hlist_node 指针,n为下一个链表元素(其实是个临时变量),head 就是 hlist_head 类型的指针了,member 为自己的结构体中对于链表的命名。
下一篇来写一些demo和使用心得,还有把里面比较细节的宏和函数做一些学习和总结吧(container_of 真是个牛逼东西)。
- linux kernel 中的链表(二)
- linux kernel 中的链表(一)
- linux kernel中的链表
- linux kernel 笔记(二)
- Linux kernel 分析之二十:内存管理-内核中的页表映射总结
- Linux Kernel Development 笔记(二)进程
- Linux Kernel读书笔记(二)---内存管理
- linux-kernel配置详情(二)
- 双向循环链表在 LINUX kernel 中的实现
- Linux kernel 中的链表list 使用示例
- Linux kernel中的IS_ENABLED
- 初探Linux kernel系列二
- Linux Kernel media框架(二)
- 浅析Linux Kernel 哈希路由表实现(二)
- The Linux Kernel Module Programming Guide简译(二)(转载)
- Linux Kernel开发者大会(二)—新旧面孔
- Android arm linux kernel启动流程(二)
- Android arm linux kernel启动流程(二)
- HTML 元素
- Android绘图基础
- CentOS yum安装LAMP(Apache+MySQL+PHP)
- JS使用正则+JSON对HTML模板进行数据填充
- Android Studio SVN使用和VisualSVN-Server配置(图解)
- linux kernel 中的链表(二)
- 为什么用Java(转载知乎)
- 一天一命令 <mkdir\rmdir\rm\mv>
- git远程仓库不完全的解决方法
- Hadoop学习资料
- poj2379 结构体复杂应用
- JavaSE学习笔记_17:Java-Math&Random类
- Android中EditText输入字数统计和限制
- Fibonacci numbers