关于list_for_each_entry相关函数

2016-07-24  本文已影响0人  哲影

offsetof宏

定义:

#define offsetof(TYPE, MEMBER) ((size_t)&((TYPE *)0)->MEMBER)

该宏先将0转换成TYPE型指针,即形成一个指向地址0TYPE指针,然后对TYPE中的MEMBER成员进行取址,而整个TYPE结构体的起始地址是0,那么这里取得的MEMBER的地址实际上等同于在TYPE中的相对偏移量。

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) );})      

可以看到container_of被预定义成一个函数,它首先通过((type *)0)->member定义member类型的指针__mptr,这个指针指向ptr,获取到了我们所要求的结构体所包含的member的地址,然后(char *)__mptr - offsetof(type, member),通过member成员的地址减去它在结构体中的偏移量,然后强制转换成type指针就得到了这个结构体的地址,define预定义返回最后一句表达式的值,将所求结构体指针返回。
  总结一下,container_of的功能就是通过一个指向结构体成员member的指针,求得指向整个结构体的指针。

list_entry

定义:

/**
* list_entry - get the struct for this entry
* @ptr:     the &struct list_head pointer.
* @type:     the type of the struct this is embedded in.
* @member:     the name of the list_struct within the struct.
*/
#define list_entry(ptr, type, member) \
       container_of\
       (ptr,type,member) 

从定义中可以看到,list_entry其实是container_of的一个别名而已,完全等同

list_for_each_entry

定义:

/**
* list_for_each_entry     -     iterate over list of given type
* @pos:      the type * to use as a loop cursor.
* @head:     the head for your list.
* @member:   the name of the list_struct within the struct.
*/
#define list_for_each_entry(pos, head, member)                    \
     for (pos = list_entry((head)->next, typeof(*pos), member);     \
          &pos->member != (head);      \
          pos = list_entry(pos->member.next, typeof(*pos), member))

这里强调一下双向链表及链表头的概念,建立一个双向链表通常有一个独立的用于管理链表的链表头,链表头一般不包含实体数据的,必须使用INIT_LIST_HEAD()进行初始化,表头建立后,就可以将带有数据结构的实体链表成员加入到链表张。关系如图所示。

Paste_Image.png

list_for_each_entry被预定义为一个for循环语句,for循环的第一句获取(head)->next指向的member成员的结构体指针,将pos初始化为链表中出链表头之外的第一个实体链表成员,for的第三句通过pos->member.next指针遍历整个实体链表,当pos->member.next再次指向链表头的时候,说明已经遍历完毕,退出循环。

list_for_each_entry_safe

定义:

/**
* list_for_each_entry_safe - iterate over list of given type safe against removal of list entry
* @pos:     the type * to use as a loop cursor.
* @n:       another type * to use as temporary storage
* @head:    the head for your list.
* @member:  the name of the list_struct within the struct.
*/
#define list_for_each_entry_safe(pos, n, head, member)               \
     for (pos = list_entry((head)->next, typeof(*pos), member),     \
          n = list_entry(pos->member.next, typeof(*pos), member);     \
          &pos->member != (head);                         \
          pos = n, n = list_entry(n->member.next, typeof(*n), member))

相比于list_for_each_entrylist_for_each_entry_safe指针n对链表的对下一个数据结构进行了临时存储,所以如果在遍历链表的时候可能要删除链表的当前项,用list_for_each_entry_safe可以安全的删除,而不会影响接下来的遍历过程。

上一篇下一篇

猜你喜欢

热点阅读