輸入子系統匹配過程之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)

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