linux核心學習筆記之——list_for_each_entry

來源:互聯網
上載者:User

在Linux{
tagshow(event)
}">核心{
tagshow(event)
}">源碼中,經常要對鏈表進行操作,其中一個很重要的宏是list_for_each_entry:
意思大體如下:

假設只有兩個結點,則第一個member代表head,
list_for_each_entry的作用就是迴圈遍曆每一個pos中的member子項。

圖1:
pos:                                                           pos:
___________                                        ____________
|                       |                                     |                          |
|                       |                                     |                          |
|    ...........     |                                     |   ................   |
|                       |                                     |                           |
|                       |                                     |                           |
|   member:    |                _________|__> member    |
|   {                  |                |                   |  {                       |
|        *prev;   |                |                    |       *prev;        |
|        *next;--|----------                    |        *next;-------------
|    }                 |                                      |  }                      |             |
|—^———— |                                      |____________|             |
      |                                                                                                      |
       |                                                                                                     |
       |_____________________________________________|

宏list_for_each_entry:

  1.    /**
  2. 401 * list_for_each_entry  -       iterate over list of given type
  3. 402 * @pos:        the type * to use as a loop cursor.
  4. 403 * @head:       the head for your list.
  5. 404 * @member:     the name of the list_struct within the struct.
  6. 405 */
  7. 406#define list_for_each_entry(pos, head, member)                          /
  8. 407        for (pos = list_entry((head)->next, typeof(*pos), member);      /
  9. 408             prefetch(pos->member.next), &pos->member != (head);        /
  10. 409             pos = list_entry(pos->member.next, typeof(*pos), member))

複製代碼

list_entry((head)->next, typeof(*pos), member)返回(head)->next物理指標所處位置向前減去offsetof()個位元組資料之後, 其父變數pos的物理地址,父變數的類型在{
tagshow(event)
}">編譯時間由typeof(*pos){
tagshow(event)
}">自動返回.
所以list_for_each_entry遍曆head下面掛接的類型為typeof(*pos)的childs結構體們,當然每個child結構體包含struct list_head node之類相似的雙向鏈表list_head類型項,就這樣通過迴圈pos將依次指向雙向鏈表上的各個child.(member就是child類型中被定義的變數名)

其中用到了函數list_entry():
這個函數的作用在圖1中表示就是可以通過已知的指向member子項的指標,獲得整個結構體的指標(地址)

  1. /**
  2. 329 * list_entry - get the struct for this entry
  3. 330 * @ptr:        the &struct list_head pointer.
  4. 331 * @type:       the type of the struct this is embedded in.
  5. 332 * @member:     the name of the list_struct within the struct.
  6. 333 */
  7. 334#define list_entry(ptr, type, member) /
  8. 335        container_of(ptr, type, member)

複製代碼

和函數prefetch:

  1. #define prefetch(x) __builtin_prefetch(x)

複製代碼

其中用到了builtin_prefetch:
prefetch的含義是告訴cpu那些元素有可能馬上就要用到,告訴cpu預取一下,這樣可以提高速度
其中用到了函數container_of():

  1. /**
  2. 487 * container_of - cast a member of a structure out to the containing structure
  3. 488 * @ptr:        the pointer to the member.
  4. 489 * @type:       the type of the container struct this is embedded in.
  5. 490 * @member:     the name of the member within the struct.
  6. 491 *
  7. 492 */
  8. 493#define container_of(ptr, type, member) ({                      /
  9. 494        const typeof( ((type *)0)->member ) *__mptr = (ptr);    /
  10. 495        (type *)( (char *)__mptr - offsetof(type,member) );})

複製代碼

下面這個連結講container_of的作用,很詳細了:
http://blog.china{
tagshow(event)
}">unix.net/u1/58968/showart_461749.html

再附一個很好的測試container_of作用的連結:
http://hi.baidu.com/xiquanlian/blog/item/a070d658642ea482810a18e3.html

其中又用到了offsetof()函數:
lxr上找到的源碼:

  1. #define offset_of(type, memb) /
  2.   47        ((unsigned long)(&((type *)0)->memb))

複製代碼

轉一篇網上對它的分析:
原文連結在這:
http://cutebunny.blog.51cto.com/301216/67517
offsetof(TYPE, MEMBER)
該宏在Linux核心代碼(版本2.6.22)中定義如下:
#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER);
分析:
(TYPE *)0,將 0 強制轉換為 TYPE 型指標,記 p = (TYPE *)0,p是指向TYPE的指標,它的值是0。那麼 p->MEMBER 就是 MEMBER 這個元素了,而&(p->MEMBER)就是MENBER的地址,而基地址為0,這樣就巧妙的轉化為了TYPE中的位移量。再把結果強制轉 換為size_t型的就OK了,size_t其實也就是int。
typedef __{
tagshow(event)
}">kernel_size_t  size_t;
typedef unsigned int __kernel_size_t;
可見,該宏的作用就是求出MEMBER在TYPE中的位移量。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.