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 结构

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 真是个牛逼东西)。

0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 在唯品会上买的水果坏了怎么办 美团极速退款后商家仍然送餐怎么办 我的拼多多商家密码忘了怎么办 特约金服扣款连续扣了两次怎么办? 拼多多拒绝退款联系客服退款怎么办 镇江新设名称申报中字号怎么办 创维电视只有声音没有图像怎么办 京东E卡有密码忘记卡号怎么办? 香香鞋上的饰品老掉怎么办 联壁金融资金冻结提现不出来怎么办 联壁金融提现不到帐怎么办 联壁金融提现迟迟不到帐怎么办 客户说平安福现金价值低怎么办 2个月宝宝肚脐凸出来怎么办 西安华润万家预付卡丢了怎么办 租房签了一年合同想走怎么办 京东寄包裹在速递易里面该怎么办 翼码科技辅助码被删掉了怎么办 用别人的身份证注册的手机号怎么办 大v线做到假线了怎么办 有个摄像头网段不同搜不到怎么办 百度网盘离线下载有违规内容怎么办 抖音上传的照片与音乐不同步怎么办 社保卡里面的钱用完了怎么办 医保卡里面的钱用完了怎么办 手机通知栏变成了搜索栏怎么办 小米手机账号密码忘了手机号怎么办 暑假工没签合同押工资了的怎么办 在日本雅虎拍卖网站买到假货怎么办 没有百度糯米账号但是买票了怎么办 拼多多商家版登陆密码忘记了怎么办 安卓下载的软件闪退怎么办 老司机影视院开通会员看不了怎么办 梦幻西游手游苹果手机打不开怎么办 拼多多笔订单被判定虚假发货怎么办 苹果手机微信接收不到信息怎么办 内衣穿32太小穿34空杯怎么办 楼下的把下水管道堵死了怎么办?? 微信绑定的手机号码已停机怎么办 绑定微信的手机号停机了怎么办验证 绑定手机停机微信怎么验证码怎么办