list_for_each_entry总结-编解码内核驱动

list_for_each_entry总结-编解码内核驱动

****作者:DayInAI 日期:20190124****

编解码内核驱动,会调用到list_for_each_entry来遍历。
 

1、#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);
          :从for循环的结构上可以看出pos是控制for循环的一个变量,但不是我们常用的int类型而是指针。
          :#define list_entry(ptr, type, member)     container_of(ptr, type, member)  


            1)const typeof( ((type *)0)->member ) *__mptr = (ptr);     (type *)( (char *)__mptr - offsetof(type,member) )
                 (type *)0是一个强转的操作,将0强行装换成type类型的指针。这个地址(0x0000)指向的是类型type的数据
                注意:32bit系统 为0x0000, 64bit系统 为0x00000000,这里已32bit为例子。64bit同理。
                指针就是刚才通过0强转的地址。所以也就是相当于地址0x0000 是结构体类型type的首地址,
                通过->取其中的成员变量member。


             2) const typeof( ((type *)0)->member ) *__mptr = (ptr)  定义指针
                   (type *)0)->member的作用就是得到成员变量member后,再通过typeof((type *)0)->member),就知道
                   member成员 的类型了。
                :定义一个指针变量__mptr,指向的类型是member的类型,其初始化为ptr的值。
                    ptr是container_of(ptr, type, member)的第一个参数。


             3) (type *)( (char *)__mptr - offsetof(type,member) );
                    __mptr是上面定义的member成员类型的指针,初始化为ptr,offsetof(type,member)是求出
                    member在结构体中的偏移量,其中type是结构体的类型。
                  (char *)__mptr - offsetof(type,member)就是__mptr - offset,即member类型的指针减去member结构体中的偏量。
                   一般__mptr = ptr,ptr是member的地址,那么member的地址减去member在结构体中偏移量不就是得
                  到结构体的地址了吗。

                   

     container_of的作用很明显了 -- 获得结构体的地址。那么我们需要给他提供三个参数,
     分别是:ptr:member成员的 指针type:结构体类型   member:成员member的名字。
     这样我们就能通过container_of(ptr, type, member)的返回值,得到结构体的地址。


(2)for循环执行条件  &pos->member != (head);
            prefetch(pos->member.next),&pos->member!= (head);  
         prefetch的含义是告诉cpu那些元素有可能马上就要用到,告诉cpu预取一下,这样可以提高速度,
        用于预取以提高遍历速度; &pos->member !=(head)  ,这个判断循环条件。

(3)每循环一次执行   pos = list_entry(pos->member.next, typeof(*pos), member))
           逐项向后(next 方向)移动 pos。

 

猜你喜欢

转载自blog.csdn.net/TheDayIn_CSDN/article/details/86584670
今日推荐