linux中链表函数问题

  
25
[ 标签: linux, 链表函数 ]
在学习内核链表时,有下列函数希望比较懂的人来回答以下这些函数及结构体的作用struct list_head *ptr,这个定义定义的是什么?是链表头指针ptr吗?那接上面的一句是INIT_LIST_HEAD(ptr)这句是什么意思?初始化以ptr为头指针的链表吗?另外list_for_each(*p1,*p2)(传入的是两个指向list_head结构体的指针),那这两个指针参数的区别是什么?还有list_entry(p,exp,list),这个函数返回值是名为exp的一个链表节点的地址吗?为什么不能直接用&exp?
年华似水 回答:1 人气:1 解决时间:2011-07-30 14:55

满意答案

好评率:100%
我来回答吧 不过有点复杂 我尽量解释清楚 一个问题一个问题来吧!1,ptr指针是链表的头指针,2,INIT_LIST_HEAD(ptr) 是一个宏,具体的实现参见list.h 是将ptr里的 prev和next两个指针指向自己,这样就完成了初始化。3,list_for_each(*p1,*p2) 从名字上来看就知道是遍历一个链表,p1是循环遍历过程中使用的循环变量而p2是遍历链表使用的开始点和结束点。4,第四个问题是最关键也是最难以理解的问题了。首先,我们要明白在内核中为了最大可能的通用性,内核中设计的链表和我们平常使用的链表的最大区别是内核中的链表除了prev和next之外不包含任何数据,所以在使用链表的时候,我们将struct list_head 嵌入到具体使用的带链表的数据结构中,像进程表等,内核中很多结构体都使用这种方式。例如,struct temp { int a,struct list_head list} tmp;这个时候通过链表头ptr,我们可以遍历到一个链表的任何一个位置,但是,我们只知道结构体tmp中list的位置,那么如何操作这个链表中的数据呢,这个时候就要通过list_for_entry来获得包含list对应的tmp结构的地址。在这个例子中将list的地址减掉int a所占的空间,就能得到tmp的地址。为此专门设计了一个宏,list_entry(p,exp,list)来进行这个计算。其实list_entry等价于container_of(ptr,type, member)这个宏,宏的实现是const typeof( ((type *)0)->member ) *__mptr = (ptr);\(type *)( (char *)__mptr-offsetof(type,member) );}),下面解释一下这个实现,首先解释一下 offsetof这个宏,它的实现是#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER),意思是TYPE是个struct类型,而MEMBER是这个struct中的一个成员. 因为这个struct的基地址为0, 所以MEMBER的地址就是这个成员相对于struct头地址的偏移量。回到container_of的实现上来,首先声明一个和member是相同类型的指针常量*__mptr,并初始化为ptr,再将这个值强转成char*类型再减去ptr这个指针所指向的成员在整个struct的偏移量,这样就得到了这个struct的入口地址。所以list_entry这个宏返回的是p这个链表指针对应的链表节点的结构体的入口地址。至于为什么不能用&exp,你的问题里没有上下文无法判断。比较复杂,希望你能看懂

你可能感兴趣的:(数据结构,linux,list,struct,each)