Linux内核中链表和散列表的实现原理揭秘
2011-07-14 11:37
246 查看
By沈东良(良少)http://blog.csdn.net/shendlLinux内核的实现,大量使用了数据结构,包括了数组、链表和散列表。其中用的最多的是双向循环链表。Linux内核使用的是自己定义的链表和散列表,简单而高效,使用方法也非常的别具一格。研究Linux内核的链表和散列表对于看懂Linux内核源代码有重要的意义。本文基于kernel2.6.39版本进行分析。inlinevoidINIT_LIST_HEAD(structlist_head*list)25{26list->next=list;27list->prev=list;28}29初始化散列表的链表。空的散列表链表的first==NULL。每一个散列表链表的元素初始化时next和pprev指针都是NULL,而不是指向自身。我们可以看到,散列表链表hlist_node虽然和双向循环链表list_head一样,都有两个指针,但有本质的区别。散列表链表hlist_node不是循环链表。它有头和尾,是单向的链表。散列表链表hlist_node之所以有两个指针,是为了提高插入和删除链表的效率。hlist_node的插入,只需要一个相邻的hlist_head或者hlist_node节点即可。它的删除,只需要它本身即可定位其相邻的前后两个元素。570571#defineHLIST_HEAD_INIT{.first=NULL}572#defineHLIST_HEAD(name)structhlist_headname={.first=NULL}573#defineINIT_HLIST_HEAD(ptr)((ptr)->first=NULL)574staticinlinevoidINIT_HLIST_NODE(structhlist_node*h)575{576h->next=NULL;577h->pprev=NULL;578}579inlinevoid__list_add(structlist_head*new,38structlist_head*prev,39structlist_head*next)40{41next->prev=new;42new->next=next;43new->prev=prev;44prev->next=new;45}46/*80*Deletealistentrybymakingtheprev/nextentries81*pointtoeachother.82*83*Thisisonlyforinternallistmanipulationwhereweknow84*theprev/nextentriesalready!85*/86staticinlinevoid__list_del(structlist_head*prev,structlist_head*next)87{88next->prev=prev;89prev->next=next;90}9192/**93*list_del-deletesentryfromlist.94*@entry:theelementtodeletefromthelist.95*Note:list_empty()onentrydoesnotreturntrueafterthis,theentryis96*inanundefinedstate.97*/98#ifndefCONFIG_DEBUG_LIST99staticinlinevoid__list_del_entry(structlist_head*entry)100{101__list_del(entry->prev,entry->next);102}103104staticinlinevoidlist_del(structlist_head*entry)105{106__list_del(entry->prev,entry->next);107entry->next=LIST_POISON1;108entry->prev=LIST_POISON2;109}110#else散列表链表的脱离链表代码:90staticinlinevoid__hlist_del(structhlist_node*n)591{592structhlist_node*next=n->next;593structhlist_node**pprev=n->pprev;594*pprev=next;595if(next)596next->pprev=pprev;597}598599staticinlinevoidhlist_del(structhlist_node*n)600{601__hlist_del(n);602n->next=LIST_POISON1;
Linux的链表和散列表定义在include/linux/types.h文件中
structlist_head{ 223struct list_head* next,* prev; 224}; 225
226struct hlist_head{ 227struct hlist_node* first; 228}; 229
list_head就是使用最为广泛的双向循环链表。这个数据结构可以说是LinuxKernel的基石,大量内核源代码使用了这个数据结构。hlist_head和hlist_node常常用于散列表中。230struct hlist_node{ 231struct hlist_node* next,** pprev; 232}; 233