美文网首页
关于list_for_each_entry相关函数

关于list_for_each_entry相关函数

作者: 哲影 | 来源:发表于2016-07-24 11:35 被阅读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可以安全的删除,而不会影响接下来的遍历过程。

    相关文章

      网友评论

          本文标题:关于list_for_each_entry相关函数

          本文链接:https://www.haomeiwen.com/subject/cxowjttx.html