概述
1. 哈希表的定义
linux-5.11.6include/linux/types.h //linux中关于哈希表结构体的定义
struct hlist_head {
struct hlist_node *first;
};
struct hlist_node {
struct hlist_node *next, **pprev;
};
整个哈希表结构如下图所示,其中ppre是个二级指针,它指向前一个节点的第一个指针变量,例如node1的ppre指向mylist的first指针,node2的ppre指向node1的next指针。
2. 哈希表的声明和初始化、节点增加、遍历等
(1)哈希表的声明和初始化
linux-5.11.6includelinuxlist.h
//hlist数据结构的操作函数和宏
#define HLIST_HEAD_INIT { .first = NULL }
#define HLIST_HEAD(name) struct hlist_head name = { .first = NULL }
#define INIT_HLIST_HEAD(ptr) ((ptr)->first = NULL)
static inline void INIT_HLIST_NODE(struct hlist_node *h)
{
h->next = NULL;
h->pprev = NULL;
}
(2)在哈希表中增加节点
在内核代码list.h中增加节点的函数为:
//把一个哈希链表的节点插入到哈希链表的头节点的后边
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_behind(struct hlist_node *n,
struct hlist_node *prev)
static inline void hlist_add_fake(struct hlist_node *n)
(3)遍历哈希表
linux-5.11.6includelinuxlist.h
#define hlist_for_each(pos, head)
for (pos = (head)->first; pos ; pos = pos->next)
头插法增加节点参考下图:
hlist_add_before作用是把一个节点插入到一个哈希链表的节点的前边,首先把将要插入的节点的pprev成员变量指向next的前边的节点,要插入的节点的next指向下一个节点,然后next节点的pprev就要指向已经插入的节点的next节点的地址,已经插入的节点的pprev指向的前一个节点的值就要变成已经插入节点的地址
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;
}
内核驱动代码如下:
// hashlist.c
// Created by linux on 2020/9/25.
//
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/list.h>
#define N 10
//数字链表
struct numlist{
struct hlist_head hlistHead;
};
//数字链表节点
struct numnode{
int num;
struct hlist_node hlistNode;
};
struct numlist nhead;
struct numnode nnode;
static int __init hlist_init(void){
//init head node
struct hlist_node *pos;
struct numnode *listnode;
int i;
struct numnode *p;
printk("hashlist is starting...n");
//初始化头节点
INIT_HLIST_HEAD(&nhead.hlistHead);
for ( i = 0; i < N; ++i) {
listnode = (struct numnode *)kmalloc(sizeof(struct numnode),GFP_KERNEL);
listnode->num = i + 1;
//头插法,添加节点在头节点之前
hlist_add_head(&(listnode->hlistNode), &nhead.hlistHead);
printk("Node %d has added to the hash list...n",i+1);
}
//遍历链表
i = 1;
hlist_for_each(pos, &nhead.hlistHead){ //移动pos的值
//使用contain_of, 根据元素hlistNode的值得到用户结构指针
p = hlist_entry(pos, struct numnode, hlistNode);
printk("Node %d data:%dn",i,p->num);
i++;
}
return 0;
}
static void __exit hashlist_exit(void){
struct hlist_node *pos,*n;
struct numnode *p;
int i;
i = 1;
//遍历数字链表,根据链表头hlistHead遍历
hlist_for_each_safe(pos,n,&nhead.hlistHead){
hlist_del(pos); //删除哈希节点
//取得删除节点的数据域值
p = hlist_entry(pos,struct numnode,hlistNode);
kfree(p);
printk("Node %d has removed from the hashlist ...n",i++);
}
printk("hash list is exiting...n");
}
module_init(hlist_init);
module_exit(hashlist_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("linux");
Makefile
obj-m := hashlist.o
CURRENT_PATH := $(shell pwd)
LINUX_KERNEL := $(shell uname -r)
LINUX_KERNEL_PATH :=/usr/src/linux-headers-$(LINUX_KERNEL)
all:
make -C $(LINUX_KERNEL_PATH) M=$(CURRENT_PATH) modules
clean:
make -C $(LINUX_KERNEL_PATH) M=$(CURRENT_PATH) clean
执行结果:
本文来自于:LINUX中哈希表的原理与应用
最后
以上就是美满彩虹为你收集整理的LINUX中哈希表的原理与应用的全部内容,希望文章能够帮你解决LINUX中哈希表的原理与应用所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复