本文是转载文章,如果有授权问题,请联系我删除。
https://danielmaker.github.io/blog/linux/list_hlist_hashtable.html
List
linux里的list定义:include/linux/types.h
struct list_head {
struct list_head *next, *prev;
};
container_of
/**
* container_of - cast a member of a structure out to the containing structure
* @ptr: the pointer to the member.
* @type: the type of the container struct this is embedded in.
* @member: the name of the member within the struct.
*/
#define container_of(ptr, type, member) ({ \
const typeof( ((type *)0)->member ) *__mptr = (ptr); \
(type *)( (char *)__mptr - offsetof(type, member) );})
其中使用的 offsetof 是C89/C99标准里包含的操作符。
typeof是GNUC标准特有的。
typeof这一行的作用:ptr与member类型不匹配时,编译会产生warnning。
链表操作:
list_empty(head) - tests whether a list is empty
list_add(new_entry, head) - adds a new entry. Insert a new entry after the specified head.
list_del(entry) - deletes entry from list.
list_for_each(pos, head) - iterate over a list
HList and Hashtable
Hlist的定义在 include/linux/types.h
struct hlist_head {
struct hlist_node *first;
};
struct hlist_node {
struct hlist_node *next, **pprev;
};
解决哈希冲突(关键字key值不同,但hash(key)的值相同):
具有相同hash值的节点会放在同一条hlist中。
1.为节省空间,hlist_head只使用一个first指针指向后边的 hlist_node ,即不存在指向链表尾结点的指针。
2.这里的pprev是二级指针,它指向的是前一个节点的next成员。
好处是即使要删除的节点是"最前边的节点",也可以通过 *pprev = next 直接修改指针的指向。
// deletes entry from hlist
void __hlist_del(struct hlist_node* entry)
{
struct hlist_node *next = entry->next;
struct hlist_node **pprev = entry->pprev;
*pprev = next;
if (next)
next->pprev = pprev;
}
哈希表的操作:
hash_init - initialize a hash table
hash_empty - check whether a hashtable is empty
hash_add - add an object to a hashtable
hash_del - remove an object from a hashtable
hash_for_each - iterate over a hashtable
hash_for_each_possible - iterate over all possible objects hashing to the same bucket
附上原作者的代码地址:
https://github.com/danielmaker/linux_study/tree/master/list_example
完。