输入子系统匹配过程之list_for_each_entry()函数分析

转载的文章:输入子系统匹配过程之list_for_each_entry()函数分析
重点:
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);  \
        prefetch(pos->member.next), &pos->member != (head);     \
        pos = list_entry(pos->member.next, typeof(*pos), member))

时刻注意这是一个宏函数,第三个参数member也是替换字符串用的,是结构体成员的名称,它的作用是提供一个数据类型,宏展开成一个函数后,也并没有引用member传来的地址,pos->member不是第三个参数member。

第一行pos = list_entry((head)->next, typeof(*pos), member)的作用就是返回
head->next所指向的member 所在的pos类型结构体的首地址。

第二句prefetch(pos->member.next), &pos->member != (head)是循环条件, 先不管,不影响分析。

第三句pos = list_entry(pos->member.next, typeof(*pos), member))和第一句一样, pos指向的是下一个member所在的pos类型结构体的首地址,这样pos就历遍了一个由pos类型结构体组成的链表 一样。

{
自己的添加:
v4l2-async.c的272行函数:

int v4l2_async_register_subdev(struct v4l2_subdev *sd)
{
    struct v4l2_async_notifier *notifier;

    /*
     * No reference taken. The reference is held by the device
     * (struct v4l2_subdev.dev), and async sub-device does not
     * exist independently of the device at any point of time.
     */
    if (!sd->of_node && sd->dev)
        sd->of_node = sd->dev->of_node;

    mutex_lock(&list_lock);

    INIT_LIST_HEAD(&sd->async_list);

    list_for_each_entry(notifier, &notifier_list, list) {
        struct v4l2_async_subdev *asd = v4l2_async_belongs(notifier, sd);
        if (asd) {
            int ret = v4l2_async_test_notify(notifier, sd, asd);
            mutex_unlock(&list_lock);
            return ret;
        }
    }

    /* None matched, wait for hot-plugging */
    list_add(&sd->async_list, &subdev_list);

    mutex_unlock(&list_lock);

    return 0;
}

list_for_each_entry(notifier, &notifier_list, list)函数里的for循环只运行了一次,想要获得notifier的地址,但是notifier_list刚被初始化,其指向的next其实是指向了自己,故不符合其初始条件判断: &pos->member != (head);

#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))  

所以并不会进入该循环,但是下一行代码:list_add(&sd->async_list, &subdev_list);,相当于将其加入到注册链表里,可以查看v4l2_device_register_subdev函数,其主要功能就是添加该链表。

附:list_add和list_add_tail
调用list_add可以将一个新链表结点插入到一个已知结点的后面;
调用list_add_tail可以将一个新链表结点插入到一个已知结点的前面;

附上其网页的链接:(http://blog.sina.com.cn/s/blog_78d30f6b0102vug4.html)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章