标签:
内核里面用list_for_each_entry实在太多了,定义在linux-3.10/include/linux/list.h:
1 /** 2 * list_for_each_entry - iterate over list of given type 3 * @pos: the type * to use as a loop cursor. 4 * @head: the head for your list. 5 * @member: the name of the list_struct within the struct. 6 */ 7 #define list_for_each_entry(pos, head, member) 8 for (pos = list_entry((head)->next, typeof(*pos), member); 9 &pos->member != (head); 10 pos = list_entry(pos->member.next, typeof(*pos), member)) 11 12 /** 13 * list_entry - get the struct for this entry 14 * @ptr: the &struct list_head pointer. 15 * @type: the type of the struct this is embedded in. 16 * @member: the name of the list_struct within the struct. 17 */ 18 #define list_entry(ptr, type, member) 19 container_of(ptr, type, member)
要分析list_entry就得分析container_of,linux-3.10/include/linux/kernel.h:
1 /** 2 * container_of - cast a member of a structure out to the containing structure 3 * @ptr: the pointer to the member. 4 * @type: the type of the container struct this is embedded in. 5 * @member: the name of the member within the struct. 6 * 7 */ 8 #define container_of(ptr, type, member) ({ 9 const typeof( ((type *)0)->member ) *__mptr = (ptr); 10 (type *)( (char *)__mptr - offsetof(type,member) );})
宏定义的第一行:typeof(x)是gcc预处理,获取x的类型,这里((type *)0)->member利用p=0的指针指向相应结构体(type)的成员,typeof获取该成员的类型并定义__mptr。
第二行:#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER),跟第一行的((type *)0)->member一个样子,获取结构体(type)的偏移量,最后__mptr转换成(char *)减去自己在结构体(type)的偏移量得到结构体(type)的指针。
可以看出第一行在功能上是没有什么卵用,其实只是作为类型检测,实现一个给定成员类型(member)的指针(ptr)找到这个成员的结构体(type)功能的只在第二行。
返回看list_entry(ptr, type, member)其实就是通过ptr找到type。
再回到list_for_each_entry(pos, head, member)的实现可以知道,用list_head通过list_entry找到包含next list_head的结构体(pos)作为变量进行循环。可得要使用list_for_each_entry,struct pos里面的成员必须包含list_head。所以在linux里面的struct经常看到list_head这个成员就是这个道理
标签:
原文地址:http://www.cnblogs.com/kevinhwang/p/5734022.html