hlist_head/hlist_node

struct hlist_head {  
    struct hlist_node *first;
};  

struct hlist_node {  
    struct hlist_node *next;
    struct hlist_node **pprev;
};  

这是Linux内核代码中常用的哈希链表的结构体定义。第一个结构体存放链表头指针,first指针指向一个由hlist_node节点组成的链表,声明一个struct hlist_head数组,每个元素都指向一条链表,就形成了一个哈希表中的很多哈希桶,类似于图的邻接表。

struct hlist_node结构体中有前驱指针和后继指针,但不同于其他的数据结构,前驱指针并不是指向前一个节点,而是一个二级指针,指向前一个节点的next指针。为什么要这么设计呢,主要是为了可以统一处理节点,不必对第一个节点进行单独处理。如此一来,删除节点的函数就可以这么写:

void hlist_del(struct hlist_node *shn)   
{   
 struct hlist_node *next = shn->next;
 struct hlist_node **pprev = shn->pprev;
 *pprev = next;   

 if (next) 
 {
    next->pprev = pprev;
 }
} 

比较简洁,无须区分是否为第一个节点。

在Linux内核中,`hlist_head` 和 `hlist_node` 结构常用于实现哈希链表的查找。这里提供一个简化版的示例,假设我们有一个简单的哈希表结构 `MyHashTable` 和相关的节点结构 `MyHashNode`,它们使用 `hlist_node` 来存储数据: ```c #include <linux/list.h> // 哈希节点结构 typedef struct MyHashNode { char key; // 这里假设key是我们哈希的关键字 struct hlist_node node; } MyHashNode; // 哈希表结构 typedef struct MyHashTable { size_t size; // 哈希表大小 struct hlist_head *buckets; // 每个桶是一个hlist_head } MyHashTable; // 初始化哈希表 void my_hash_table_init(MyHashTable *table, size_t size) { table->size = size; table->buckets = kcalloc(size, sizeof(struct hlist_head), GFP_KERNEL); if (!table->buckets) panic("Failed to allocate memory for buckets"); } // 计算键值的哈希索引 static inline int hash_key(const char *key, size_t size) { return (unsigned long)key % table->size; } // 插入节点到哈希表 void my_hash_table_insert(MyHashTable *table, const char *key, void *data) { MyHashNode *node = kmalloc(sizeof(MyHashNode), GFP_KERNEL); if (!node) return; node->key = *key; // 将数据复制到节点 memcpy(&node->data, data, sizeof(void*)); // 假设数据是void* int index = hash_key(key, strlen(key)); hlist_add_tail(&node->node, &table->buckets[index]); } // 查找节点(在这里只是一个基本的例子,实际查找需要遍历链表) void *my_hash_table_search(MyHashTable *table, const char *key) { int index = hash_key(key, strlen(key)); struct hlist_node *node = table->buckets[index].first; while (node) { MyHashNode *hash_node = container_of(node, MyHashNode, node); if (hash_node->key == *key) { return hash_node->data; // 如果找到匹配,返回数据 } node = node->next; } return NULL; // 没有找到匹配 } // 示例用法 void main() { MyHashTable table; my_hash_table_init(&table, 10); // 插入一些项 my_hash_table_insert(&table, "A", (void*)0x123); my_hash_table_insert(&table, "B", (void*)0x456); // 查找并打印结果 void *found_data = my_hash_table_search(&table, "A"); if (found_data) { printk(KERN_INFO "Found key 'A': 0x%p\n", found_data); } else { printk(KERN_INFO "Key 'A' not found.\n"); } } ``` 注意这仅是一个简化的示例,实际应用中可能需要处理更多的边界情况和错误处理。此外,`hlist_head` 的操作通常在中断上下文中不是安全的,因此在实际的内核代码中可能会有所调整。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值