關(guān)于list_for_each_entry相關(guān)函數(shù)

offsetof宏

定義:

#define offsetof(TYPE, MEMBER) ((size_t)&((TYPE *)0)->MEMBER)

該宏先將0轉(zhuǎn)換成TYPE型指針,即形成一個(gè)指向地址0TYPE指針,然后對(duì)TYPE中的MEMBER成員進(jìn)行取址,而整個(gè)TYPE結(jié)構(gòu)體的起始地址是0,那么這里取得的MEMBER的地址實(shí)際上等同于在TYPE中的相對(duì)偏移量。

container_of

定義:

/**
* 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 container_of(ptr, type, member) ({                    \
     const typeof( ((type *)0)->member ) *__mptr = (ptr);     \
     (type *)( (char *)__mptr - offsetof(type,member) );})      

可以看到container_of被預(yù)定義成一個(gè)函數(shù),它首先通過((type *)0)->member定義member類型的指針__mptr,這個(gè)指針指向ptr,獲取到了我們所要求的結(jié)構(gòu)體所包含的member的地址,然后(char *)__mptr - offsetof(type, member),通過member成員的地址減去它在結(jié)構(gòu)體中的偏移量,然后強(qiáng)制轉(zhuǎn)換成type指針就得到了這個(gè)結(jié)構(gòu)體的地址,define預(yù)定義返回最后一句表達(dá)式的值,將所求結(jié)構(gòu)體指針返回。
  總結(jié)一下,container_of的功能就是通過一個(gè)指向結(jié)構(gòu)體成員member的指針,求得指向整個(gè)結(jié)構(gòu)體的指針。

list_entry

定義:

/**
* 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_entry其實(shí)是container_of的一個(gè)別名而已,完全等同

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);     \
          &pos->member != (head);      \
          pos = list_entry(pos->member.next, typeof(*pos), member))

這里強(qiáng)調(diào)一下雙向鏈表及鏈表頭的概念,建立一個(gè)雙向鏈表通常有一個(gè)獨(dú)立的用于管理鏈表的鏈表頭,鏈表頭一般不包含實(shí)體數(shù)據(jù)的,必須使用INIT_LIST_HEAD()進(jìn)行初始化,表頭建立后,就可以將帶有數(shù)據(jù)結(jié)構(gòu)的實(shí)體鏈表成員加入到鏈表張。關(guān)系如圖所示。

Paste_Image.png

list_for_each_entry被預(yù)定義為一個(gè)for循環(huán)語句,for循環(huán)的第一句獲取(head)->next指向的member成員的結(jié)構(gòu)體指針,將pos初始化為鏈表中出鏈表頭之外的第一個(gè)實(shí)體鏈表成員,for的第三句通過pos->member.next指針遍歷整個(gè)實(shí)體鏈表,當(dāng)pos->member.next再次指向鏈表頭的時(shí)候,說明已經(jīng)遍歷完畢,退出循環(huán)。

list_for_each_entry_safe

定義:

/**
* list_for_each_entry_safe - iterate over list of given type safe against removal of list entry
* @pos:     the type * to use as a loop cursor.
* @n:       another type * to use as temporary storage
* @head:    the head for your list.
* @member:  the name of the list_struct within the struct.
*/
#define list_for_each_entry_safe(pos, n, head, member)               \
     for (pos = list_entry((head)->next, typeof(*pos), member),     \
          n = list_entry(pos->member.next, typeof(*pos), member);     \
          &pos->member != (head);                         \
          pos = n, n = list_entry(n->member.next, typeof(*n), member))

相比于list_for_each_entry,list_for_each_entry_safe指針n對(duì)鏈表的對(duì)下一個(gè)數(shù)據(jù)結(jié)構(gòu)進(jìn)行了臨時(shí)存儲(chǔ),所以如果在遍歷鏈表的時(shí)候可能要?jiǎng)h除鏈表的當(dāng)前項(xiàng),用list_for_each_entry_safe可以安全的刪除,而不會(huì)影響接下來的遍歷過程。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容