Linux内核链表之哈希链表
2017-06-04 12:09
92 查看
/*
* <Filename : hlist.h>
* Date : 2017年6月4日
* Weather : cloudy day
* Author : goup 更多内容,请点击http://blog.csdn.net/weixin_37977062?viewmode=contents
*/
* 1.因为哈希链表并不需要双向循环的技能,它一般适用于单向散列的场景。
* 所以,为了减少开销,并没有用struct hlist_node{}来代表哈希表头,
* 而是重新设计struct hlist_head{}这个数据结构
*
* 2.此时,一个哈希表头就只需要4Byte了,相比于struct hlist_node{}来说,
* 存储空间已经减少了一半。这样一来,在需要大量用到哈希链表的场景,
* 其存储空间的节约是非常明显的,特别是在嵌入式设备领域。
*/
struct list_head {
struct list_head *next, //指向下一个结点的指针
*prev;
//指向上一个结点的next指针的地址
};
//哈希链表的表头
struct hlist_head {
struct hlist_node *first; //指向每一个hash桶的第一个结点的指针
};
/*
* 注意:struct hlist_node的前驱结点是一个2级指针
*
* 1.两级指针的宿命,为了间接改变一级指针所指的内存地址
*
* 2.node节点里的pprev其实指向的是其前一个节点里的第一个指针元素的地址,对于hlist_head来说,
* 它里面只有一个指针元素,就是first指针;而对于hlist_node来说,第一个指针元素就是next
*
* 3.所以,记住,当我们在代码中看到类似与*(hlist_node->pprev)这样的代码时,我们心里应该清楚,
* 此时正在哈希表里操作当前节点前一个节点里的第一个指针元素所指向的内存地址,只是以间接的方式实现罢了
*
*/
//哈希链表结点
struct hlist_node {
//*prev指向的是前驱的next域
struct hlist_node *next, **pprev;
};
//list.h
#define HLIST_HEAD_INIT { .first = NULL }
#define HLIST_HEAD(name) struct hlist_head name = { .first = NULL }
#define INIT_HLIST_HEAD(ptr) ((ptr)->first = NULL)
/***********************************************INIT_HLIST_NODE**********************************************/
/**************************************************初始化结点************************************************/
static inline void INIT_HLIST_NODE(struct hlist_node *h)
{
h->next = NULL;
h->pprev = NULL;
}
/***********************************************hlist_unhashed***********************************************/
/********************************************判断该结点是不是表头********************************************/
static inline int hlist_unhashed(const struct hlist_node *h)
{
return !h->pprev;
}
/************************************************hlist_empty*************************************************/
/************************************************判断是否为空************************************************/
static inline int hlist_empty(const struct hlist_head *h)
{
return !h->first;
}
/***************************************************删除*****************************************************/
/************************************************************************************************************/
/***************************************************删除*****************************************************/
static inline void __hlist_del(struct hlist_node *n)
{
struct hlist_node *next = n->next;
//获取指向待删除结点的下一个普通结点的指针
struct hlist_node **pprev = n->pprev;
//获取待删除结点的pprev域
*pprev = next;
//修改待删除结点的pprev域,逻辑上使待删除结点的前驱结点指向待删除结点的后继结点
//在标准的哈希链表里,因为最后一个节点的next=NULL
if (next)
next->pprev = pprev;
//设置下一个结点的pprev域
}
/***********************************************删除结点 n **************************************************/
static inline void hlist_del(struct hlist_node *n)
{
__hlist_del(n);
n->next = LIST_POISON1;
n->pprev = LIST_POISON2;
}
static inline void hlist_del_init(struct hlist_node *n)
{
if (!hlist_unhashed(n)) {
__hlist_del(n);
INIT_HLIST_NODE(n);
}
}
/**************************************************插入******************************************************/
/************************************************************************************************************/
/**************************************************头插******************************************************/
static inline void hlist_add_head(struct hlist_node *n, struct hlist_head *h)
{
struct hlist_node *first = h->first;
n->next = first;
if (first)
first->pprev = &n->next;
h->first = n;
n->pprev = &h->first;
}
/*****************************************在 next 结点前面插入 n 结点*****************************************/
/* next must be != NULL */
static inline void hlist_add_before(struct hlist_node *n,
struct hlist_node *next)
{
n->pprev = next->pprev;
n->next = next;
next->pprev = &n->next;
*(n->pprev) = n;
}
/*****************************************在 next 结点后面插入 n 结点*****************************************/
static inline void hlist_add_after(struct hlist_node *n,
struct hlist_node *next)
{
next->next = n->next;
n->next = next;
next->pprev = &n->next;
if(next->next)
next->next->pprev = &next->next;
}
/* after that we'll appear to be on some hlist and hlist_del will work */
static inline void hlist_add_fake(struct hlist_node *n)
{
n->pprev = &n->next;
}
/*
* Move a list from one list head to another. Fixup the pprev
* reference of the first entry if it exists.
*/
static inline void hlist_move_list(struct hlist_head *old,
struct hlist_head *new)
{
new->first = old->first;
if (new->first)
new->first->pprev = &new->first;
old->first = NULL;
}
/*****************************************************遍历*****************************************************/
/**************************************************************************************************************/
/******************************************************宏******************************************************/
/*************************************************hlist_entry**************************************************/
#define hlist_entry(ptr, type, member) container_of(ptr,type,member)
/***********************************************hlist_for_entry************************************************/
/*
* #define hlist_for_each(pos, head) \
* for (pos = (head)->first; pos && ({ prefetch(pos->next); 1; }); \
* pos = pos->next)
*
* //prefetch宏是一个空的实现,其值是1,因此for循环中的第二个表达式其实就等价于 pos
*/
#define hlist_for_each(pos, head) \
for (pos = (head)->first; pos ; pos = pos->next)
/*********************************************hlist_for_each_safe**********************************************/
/**********************************************用于删除结点的遍历**********************************************/
#define hlist_for_each_safe(pos, n, head) \
for (pos = (head)->first; pos && ({ n = pos->next; 1; }); \
pos = n)
/*******************************************hlist_for_each_entry*********************************************/
/***********************************************从表头开始遍历***********************************************/
/**
* hlist_for_each_entry - iterate over list of given type
* @tpos: the type * to use as a loop cursor.
//@tpos : 指向结构体的指针
* @pos: the &struct hlist_node to use as a loop cursor.
//@pos :用于循环,struct hlist_node类型
* @head: the head for your list.
//@head : 哈希桶head
* @member: the name of the hlist_node within the struct.
//member: 宿主结构体成员,即哈希桶的一个结点
*/
// ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;});
// 这个表达式的值也永远为1,但是这里tpos指向了hlist_node所在的宿主结构
#define hlist_for_each_entry(tpos, pos, head, member)
\
for (pos = (head)->first;
\
pos &&
\
({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \
pos = pos->next)
/***************************************hlist_for_each_entry_continue****************************************/
/*****************************************从 pos 下一个结点开始遍历******************************************/
/**
* hlist_for_each_entry_continue - iterate over a hlist continuing after current point
* @tpos: the type * to use as a loop cursor.
* @pos: the &struct hlist_node to use as a loop cursor.
* @member: the name of the hlist_node within the struct.
*/
#define hlist_for_each_entry_continue(tpos, pos, member)
\
for (pos = (pos)->next;
\
pos &&
\
({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \
pos = pos->next)
/*****************************************hlist_for_each_entry_from******************************************/
/*********************************************从 pos 结点开始遍历********************************************/
/**
* hlist_for_each_entry_from - iterate over a hlist continuing from current point
* @tpos: the type * to use as a loop cursor.
* @pos: the &struct hlist_node to use as a loop cursor.
* @member: the name of the hlist_node within the struct.
*/
#define hlist_for_each_entry_from(tpos, pos, member)
\
for (; pos &&
\
({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \
pos = pos->next)
/*****************************************hlist_for_each_entry_safe******************************************/
/****************************************从头开始遍历,用于删除结点******************************************/
/**
* 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)
更多内容,请点击http://blog.csdn.net/weixin_37977062?viewmode=contents
* <Filename : hlist.h>
* Date : 2017年6月4日
* Weather : cloudy day
* Author : goup 更多内容,请点击http://blog.csdn.net/weixin_37977062?viewmode=contents
*/
Linux内核数据结构之哈希链表
/** 1.因为哈希链表并不需要双向循环的技能,它一般适用于单向散列的场景。
* 所以,为了减少开销,并没有用struct hlist_node{}来代表哈希表头,
* 而是重新设计struct hlist_head{}这个数据结构
*
* 2.此时,一个哈希表头就只需要4Byte了,相比于struct hlist_node{}来说,
* 存储空间已经减少了一半。这样一来,在需要大量用到哈希链表的场景,
* 其存储空间的节约是非常明显的,特别是在嵌入式设备领域。
*/
结点
//include/linux/types.hstruct list_head {
struct list_head *next, //指向下一个结点的指针
*prev;
//指向上一个结点的next指针的地址
};
//哈希链表的表头
struct hlist_head {
struct hlist_node *first; //指向每一个hash桶的第一个结点的指针
};
/*
* 注意:struct hlist_node的前驱结点是一个2级指针
*
* 1.两级指针的宿命,为了间接改变一级指针所指的内存地址
*
* 2.node节点里的pprev其实指向的是其前一个节点里的第一个指针元素的地址,对于hlist_head来说,
* 它里面只有一个指针元素,就是first指针;而对于hlist_node来说,第一个指针元素就是next
*
* 3.所以,记住,当我们在代码中看到类似与*(hlist_node->pprev)这样的代码时,我们心里应该清楚,
* 此时正在哈希表里操作当前节点前一个节点里的第一个指针元素所指向的内存地址,只是以间接的方式实现罢了
*
*/
//哈希链表结点
struct hlist_node {
//*prev指向的是前驱的next域
struct hlist_node *next, **pprev;
};
//list.h
#define HLIST_HEAD_INIT { .first = NULL }
#define HLIST_HEAD(name) struct hlist_head name = { .first = NULL }
#define INIT_HLIST_HEAD(ptr) ((ptr)->first = NULL)
/***********************************************INIT_HLIST_NODE**********************************************/
/**************************************************初始化结点************************************************/
static inline void INIT_HLIST_NODE(struct hlist_node *h)
{
h->next = NULL;
h->pprev = NULL;
}
/***********************************************hlist_unhashed***********************************************/
/********************************************判断该结点是不是表头********************************************/
static inline int hlist_unhashed(const struct hlist_node *h)
{
return !h->pprev;
}
/************************************************hlist_empty*************************************************/
/************************************************判断是否为空************************************************/
static inline int hlist_empty(const struct hlist_head *h)
{
return !h->first;
}
2.删除
/************************************************************************************************************//***************************************************删除*****************************************************/
/************************************************************************************************************/
/***************************************************删除*****************************************************/
static inline void __hlist_del(struct hlist_node *n)
{
struct hlist_node *next = n->next;
//获取指向待删除结点的下一个普通结点的指针
struct hlist_node **pprev = n->pprev;
//获取待删除结点的pprev域
*pprev = next;
//修改待删除结点的pprev域,逻辑上使待删除结点的前驱结点指向待删除结点的后继结点
//在标准的哈希链表里,因为最后一个节点的next=NULL
if (next)
next->pprev = pprev;
//设置下一个结点的pprev域
}
/***********************************************删除结点 n **************************************************/
static inline void hlist_del(struct hlist_node *n)
{
__hlist_del(n);
n->next = LIST_POISON1;
n->pprev = LIST_POISON2;
}
static inline void hlist_del_init(struct hlist_node *n)
{
if (!hlist_unhashed(n)) {
__hlist_del(n);
INIT_HLIST_NODE(n);
}
}
3.插入
/************************************************************************************************************//**************************************************插入******************************************************/
/************************************************************************************************************/
/**************************************************头插******************************************************/
static inline void hlist_add_head(struct hlist_node *n, struct hlist_head *h)
{
struct hlist_node *first = h->first;
n->next = first;
if (first)
first->pprev = &n->next;
h->first = n;
n->pprev = &h->first;
}
/*****************************************在 next 结点前面插入 n 结点*****************************************/
/* next must be != NULL */
static inline void hlist_add_before(struct hlist_node *n,
struct hlist_node *next)
{
n->pprev = next->pprev;
n->next = next;
next->pprev = &n->next;
*(n->pprev) = n;
}
/*****************************************在 next 结点后面插入 n 结点*****************************************/
static inline void hlist_add_after(struct hlist_node *n,
struct hlist_node *next)
{
next->next = n->next;
n->next = next;
next->pprev = &n->next;
if(next->next)
next->next->pprev = &next->next;
}
/* after that we'll appear to be on some hlist and hlist_del will work */
static inline void hlist_add_fake(struct hlist_node *n)
{
n->pprev = &n->next;
}
/*
* Move a list from one list head to another. Fixup the pprev
* reference of the first entry if it exists.
*/
static inline void hlist_move_list(struct hlist_head *old,
struct hlist_head *new)
{
new->first = old->first;
if (new->first)
new->first->pprev = &new->first;
old->first = NULL;
}
4.遍历
/**************************************************************************************************************//*****************************************************遍历*****************************************************/
/**************************************************************************************************************/
/******************************************************宏******************************************************/
/*************************************************hlist_entry**************************************************/
#define hlist_entry(ptr, type, member) container_of(ptr,type,member)
/***********************************************hlist_for_entry************************************************/
/*
* #define hlist_for_each(pos, head) \
* for (pos = (head)->first; pos && ({ prefetch(pos->next); 1; }); \
* pos = pos->next)
*
* //prefetch宏是一个空的实现,其值是1,因此for循环中的第二个表达式其实就等价于 pos
*/
#define hlist_for_each(pos, head) \
for (pos = (head)->first; pos ; pos = pos->next)
/*********************************************hlist_for_each_safe**********************************************/
/**********************************************用于删除结点的遍历**********************************************/
#define hlist_for_each_safe(pos, n, head) \
for (pos = (head)->first; pos && ({ n = pos->next; 1; }); \
pos = n)
/*******************************************hlist_for_each_entry*********************************************/
/***********************************************从表头开始遍历***********************************************/
/**
* hlist_for_each_entry - iterate over list of given type
* @tpos: the type * to use as a loop cursor.
//@tpos : 指向结构体的指针
* @pos: the &struct hlist_node to use as a loop cursor.
//@pos :用于循环,struct hlist_node类型
* @head: the head for your list.
//@head : 哈希桶head
* @member: the name of the hlist_node within the struct.
//member: 宿主结构体成员,即哈希桶的一个结点
*/
// ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;});
// 这个表达式的值也永远为1,但是这里tpos指向了hlist_node所在的宿主结构
#define hlist_for_each_entry(tpos, pos, head, member)
\
for (pos = (head)->first;
\
pos &&
\
({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \
pos = pos->next)
/***************************************hlist_for_each_entry_continue****************************************/
/*****************************************从 pos 下一个结点开始遍历******************************************/
/**
* hlist_for_each_entry_continue - iterate over a hlist continuing after current point
* @tpos: the type * to use as a loop cursor.
* @pos: the &struct hlist_node to use as a loop cursor.
* @member: the name of the hlist_node within the struct.
*/
#define hlist_for_each_entry_continue(tpos, pos, member)
\
for (pos = (pos)->next;
\
pos &&
\
({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \
pos = pos->next)
/*****************************************hlist_for_each_entry_from******************************************/
/*********************************************从 pos 结点开始遍历********************************************/
/**
* hlist_for_each_entry_from - iterate over a hlist continuing from current point
* @tpos: the type * to use as a loop cursor.
* @pos: the &struct hlist_node to use as a loop cursor.
* @member: the name of the hlist_node within the struct.
*/
#define hlist_for_each_entry_from(tpos, pos, member)
\
for (; pos &&
\
({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \
pos = pos->next)
/*****************************************hlist_for_each_entry_safe******************************************/
/****************************************从头开始遍历,用于删除结点******************************************/
/**
* 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)
更多内容,请点击http://blog.csdn.net/weixin_37977062?viewmode=contents
相关文章推荐
- Linux内核数据结构之链表list.h
- 内核数据结构移植
- Go语言移植Linux内核数据结构hlist
- hlist内核哈希链表应用-解决散列表表的冲突问题
- 常用Linux命令:netstat
- find命令常用介绍
- CentOS 6.5 版本下 MySQL 5.1.73 版本的安装
- linux 学习文档(二)
- Linux 内核剖析
- Linux远程桌面(一)
- [Command]Linux 文件格式化处理
- Linux vsftpd 的安装
- CentOS7.2部署FTP
- 常用Linux命令:scp
- netstat查看系统连接数及当前连接IP
- 【Linux】七个运行级别
- sar命令
- Linux学习之二十五(Linux文档压缩及归档,gz/bz2/xz/zip/Z)
- centos : yacc&lex gcc cannot find -ll/-lfl
- Linux学习之二十四(硬盘管理及文件系统管理:fdisk/mke2fs/tune2fs)