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;-------------
|    }                 |                                      |  }                      |             |
|—^———— |                                      |____________|             |
      |                                                                                                      |
       |                                                                                                     |
       |_____________________________________________|

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM