zoukankan      html  css  js  c++  java
  • linux之list_for_each和list_for_each_entry函数

    比较:
    1.list_for_each和list_for_each_entry都是遍历链表的两个宏,本质上都是for循环。
    2.他们做的事情本质上都一样,A.获取链表头,B.判断链表项是不是链表头,C.指向链表的下一项。
    3.他们的区别:list_for_each遍历的链表,其链表项不属于某个结构体。或者说不关心它是不是包含在某个结构体中。
    list_for_each_entry遍历的链表,其每一项都是某个结构体中的成员,单纯遍历链表还不行,还要找到包含这个
    链表项的结构体的地址,从而为下一步应用该结构体做好准备。

    一、list_for_each

    list_for_each内核中的定义:
    /**
     * list_for_each - iterate over a list
     * @pos: the &struct list_head to use as a loop cursor.
     * @head: the head for your list.
     */
    #define list_for_each(pos, head) 
    for (pos = (head)->next; pos != (head); pos = pos->next)

    一个简单的for循环。

    循环的初始化工作:pos指向链表头的下一项。

    循环的条件:pos不是链表头。

    每次循环要做的事情:pos指向链表中的下一项

    二、list_for_each_entry

    /**
     * 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 offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
    #define container_of(ptr, type, member) ({          
    const typeof(((type *)0)->member)*__mptr = (ptr);    
        (type *)((char *)__mptr - offsetof(type, member)); })
    
    /**
     * 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_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))

    将for循环分解为一下三点:

    1. for循环初始化      pos = list_entry((head)->next, typeof(*pos), member);

    2. for循环执行条件  &pos->member != (head);

    3. 每循环一次执行   pos = list_entry(pos->member.next, typeof(*pos), member))

    解析:

    1、(type *)0是一个强转的操作,将0强行装换成type类型的指针。

          type类型是container_of的第二个参数,所以在使用container_of时第二个参数应该传类型。

    2、pos = list_entry((head)->next, typeof(*pos), member)  , list_entry ---> container_of,因为list_entry第二个参数是typeof(* pos)。

         typeof()是取变量的类型,这里是取指针pos所指向数据的类型

    3、(type *)0)->member的作用就是得到成员变量member后,再通过typeof((type *)0)->member),就知道member成员的类型。

    4、offsetof(type,member)是求出member在结构体中的偏移量,其中type是结构体的类型。

        (char *)__mptr - offsetof(type,member)就是 __mptr - offset,即member类型的指针减去member在结构体中的偏移量。

         一般__mptr = ptr,ptr是member的地址,那么member的地址减去member在结构体中偏移量不就是得到结构体的地址。

    5、container_of的作用很明显了 -- 获得结构体的地址。

       那么我们需要给他提供三个参数,分别是:ptr:member成员的指针   type:结构体类型   member:成员member的名字。

    结构体pos中包含链表member,遍历pos中的member成员。

    pos:                                                           pos:
    ___________                                        ____________
    |                       |                                     |                          |
    |                       |                                     |                          |
    |    ...........     |                                     |   ................   |
    |                       |                                     |                           |
    |                       |                                     |                           |
    |   member:    |                _________|__> member    |
    |   {                  |                |                   |  {                       |
    |        *prev;   |                |                    |       *prev;        |
    |        *next;--|----------                    |        *next;-------------
    |    }                 |                                      |  }                      |             |
    |—^———— |                                      |____________|             |
          |                                                                                                      |
           |                                                                                                     |
           |_____________________________________________|

  • 相关阅读:
    js技巧收集(200多个)
    我的博客开张了,欢迎大家前来做客
    认识ASP.NET配置文件Web.config
    C#纯数学方法递归实现货币数字转换中文
    Asp.Net细节性问题技巧精萃(转载)
    ASP.NET2.0+SQL Server2005构建多层应用
    ASP.NET页面间的传值的几种方法(转载)
    介绍几种 ADO.net 中的数据库连接方式
    hdu 1401
    poj 1338 丑数
  • 原文地址:https://www.cnblogs.com/ggzhangxiaochao/p/13801328.html
Copyright © 2011-2022 走看看