轉載的文章:輸入子系統匹配過程之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, ¬ifier_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, ¬ifier_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)