资源描述:
《linux2.6内核设备驱动模型精华》由会员上传分享,免费在线阅读,更多相关内容在行业资料-天天文库。
1、linux内核部件分析(一)——连通世界的list在linux内核中,有一种通用的双向循环链表,构成了各种队列的基础。链表的结构定义和相关函数均在include/linux/list.h中,下面就来全面的介绍这一链表的各种API。structlist_head{structlist_head*next,*prev;};这是链表的元素结构。因为是循环链表,表头和表中节点都是这一结构。有prev和next两个指针,分别指向链表中前一节点和后一节点。#defineLIST_HEAD_INIT(name){&(name),&(na
2、me)}#defineLIST_HEAD(name)structlist_headname=LIST_HEAD_INIT(name)staticinlinevoidINIT_LIST_HEAD(structlist_head*list){list->next=list;list->prev=list;}在初始化的时候,链表头的prev和next都是指向自身的。staticinlinevoid__list_add(structlist_head*new,structlist_head*prev,structlist_hea
3、d*next){next->prev=new;new->next=next;new->prev=prev;prev->next=new;}staticinlinevoidlist_add(structlist_head*new,structlist_head*head){__list_add(new,head,head->next);}staticinlinevoidlist_add_tail(structlist_head*new,structlist_head*head){__list_add(new,head->pr
4、ev,head);}双向循环链表的实现,很少有例外情况,基本都可以用公共的方式来处理。这里无论是加第一个节点,还是其它的节点,使用的方法都一样。另外,链表API实现时大致都是分为两层:一层外部的,如list_add、list_add_tail,用来消除一些例外情况,调用内部实现;一层是内部的,函数名前会加双下划线,如__list_add,往往是几个操作公共的部分,或者排除例外后的实现。staticinlinevoid__list_del(structlist_head*prev,structlist_head*next){
5、next->prev=prev;prev->next=next;}staticinlinevoidlist_del(structlist_head*entry){__list_del(entry->prev,entry->next);entry->next=LIST_POISON1;entry->prev=LIST_POISON2;}staticinlinevoidlist_del_init(structlist_head*entry){__list_del(entry->prev,entry->next);INIT_LI
6、ST_HEAD(entry);}list_del是链表中节点的删除。之所以在调用__list_del后又把被删除元素的next、prev指向特殊的LIST_POSITION1和LIST_POSITION2,是为了调试未定义的指针。list_del_init则是删除节点后,随即把节点中指针再次初始化,这种删除方式更为实用。staticinlinevoidlist_replace(structlist_head*old,structlist_head*new){new->next=old->next;new->next->pr
7、ev=new;new->prev=old->prev;new->prev->next=new;}staticinlinevoidlist_replace_init(structlist_head*old,structlist_head*new){list_replace(old,new);INIT_LIST_HEAD(old);}list_replace是将链表中一个节点old,替换为另一个节点new。从实现来看,即使old所在地链表只有old一个节点,new也可以成功替换,这就是双向循环链表可怕的通用之处。list_re
8、place_init将被替换的old随即又初始化。staticinlinevoidlist_move(structlist_head*list,structlist_head*head){__list_del(list->prev,list->next);list_add(list,head);}sta