0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫(xiě)文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

container_of()宏,太妙了~

嵌入式情報(bào)局 ? 來(lái)源:嵌入式情報(bào)局 ? 2023-09-10 10:59 ? 次閱讀

container_of(ptr, type, member)宏的作用

該宏的作用是通過(guò)結(jié)構(gòu)體成員的地址和結(jié)構(gòu)體類型推導(dǎo)出結(jié)構(gòu)體的地址,type是指結(jié)構(gòu)體的類型,member是成員在結(jié)構(gòu)體中的名字,ptr是該成員在type結(jié)構(gòu)體中的地址。

container_of(ptr, type, member)宏解析

linux 源碼的 toolsincludelinuxkernel.h文件下,container_of()的定義如下:

#ifndefcontainer_of
/**
*container_of-castamemberofastructureouttothecontainingstructure
*@ptr:thepointertothemember.
*@type:thetypeofthecontainerstructthisisembeddedin.
*@member:thenameofthememberwithinthestruct.
*
*/
#definecontainer_of(ptr,type,member)({
consttypeof(((type*)0)->member)*__mptr=(ptr);
(type*)((char*)__mptr-offsetof(type,member));})
#endif

container_of() 宏的定義中的 offsetof(TYPE, MEMBER)typeof() 初學(xué)者可能會(huì)對(duì)其很陌生,所以我們要先從理解 offsetof(TYPE, MEMBER)typeof() 的作用開(kāi)始。

offsetof(TYPE, MEMBER)

本質(zhì)也是個(gè)宏定義,在 linux 源碼的 toolsincludelinuxkernel.h 文件下定義如下:

#ifndefoffsetof
#defineoffsetof(TYPE,MEMBER)((size_t)&((TYPE*)0)->MEMBER)
#endif

offsetof 宏中的 TYPE 是指結(jié)構(gòu)體的類型,MEMBER 是指結(jié)構(gòu)體中的某個(gè)成員,作用是求出該成員的在該結(jié)構(gòu)體中的偏移量。該宏首先將 0 (地址0)轉(zhuǎn)化為 TYPE * 的結(jié)構(gòu)體指針,表示地址為 0 的結(jié)構(gòu)體指針,然后通過(guò)取地址符 &((TYPE *)0)->MEMBER) 取出該結(jié)構(gòu)體指針中 MEMBER 成員的地址,最后再將地址值強(qiáng)轉(zhuǎn)為 size_t 類型(內(nèi)核中為 unsigned long 類型)即表示 MEMBER 成員在結(jié)構(gòu)體中的偏移量。要理解該過(guò)程需要了解對(duì)結(jié)構(gòu)體的內(nèi)存分布,如圖,結(jié)構(gòu)體的內(nèi)存分配是連續(xù)的,當(dāng)結(jié)構(gòu)體的地址為0時(shí),成員的地址即為該成員的偏移量。

758a6386-4f09-11ee-a25d-92fbcf53809c.png

實(shí)例:

#include

#ifndefoffsetof
#defineoffsetof(TYPE,MEMBER)((size_t)&((TYPE*)0)->MEMBER)
#endif

typedefstruct_offset
{
charmember_0;
intmember_1;
charmember_2;
}offset;

intmain()
{
printf("%d
",offsetof(offset,member_0));
printf("%d
",offsetof(offset,member_1));
printf("%d
",offsetof(offset,member_2));


return0;

}

輸出:

75a02496-4f09-11ee-a25d-92fbcf53809c.png

offsetof實(shí)例結(jié)果輸出

typeof()

typeof()GNU C 中的一個(gè)關(guān)鍵字,和 sizeof() 一樣都是 C 語(yǔ)言中的關(guān)鍵字而不是函數(shù)。作用是返回傳入數(shù)據(jù)的類型。實(shí)例:

#include

intmain()
{
inta=3;
typeof(a)b=a;/*求出a變量的類型,并創(chuàng)建一個(gè)b變量*/


printf("a=%db=%d",a,b);

return0;
}

輸出:

75b50758-4f09-11ee-a25d-92fbcf53809c.png

img

container_of(ptr, type, member)

了解了 offsetof() 宏和 typeof 關(guān)鍵字之后就比較好理解 container_of 宏的作用了。

consttypeof(((type*)0)->member)*__mptr=(ptr)

該代碼的作用實(shí)際上是將 0 轉(zhuǎn)化為 type * 結(jié)構(gòu)體類型,再取出結(jié)構(gòu)體中的MEMBER成員 (type *)0)->member, 再通過(guò) typeof 關(guān)鍵字獲取 MEMBER 成員的類型,并定義一個(gè) MEMBER 成員類型的指針 const typeof(((type *)0)->member) * __mptr,將傳入的 ptr 指針賦值給 __mptr__mptr = (ptr)。

(type*)((char*)__mptr-offsetof(type,member));

該代碼是將獲取的 MEMBER 成員地址強(qiáng)轉(zhuǎn)為 char *(強(qiáng)轉(zhuǎn)的目的是考慮指針的加減的實(shí)質(zhì)是指針在內(nèi)存的偏移,偏移量為指針類型所占字節(jié)的個(gè)數(shù)),減去 MEMBER 成員在 type 結(jié)構(gòu)體中的偏移量,強(qiáng)轉(zhuǎn)為 type * 后得到結(jié)構(gòu)體的地址。實(shí)例:

#include

#ifndefoffsetof
#defineoffsetof(TYPE,MEMBER)((size_t)&((TYPE*)0)->MEMBER)
#endif

#ifndefcontainer_of
#definecontainer_of(ptr,type,member)({
consttypeof(((type*)0)->member)*__mptr=(ptr);
(type*)((char*)__mptr-offsetof(type,member));})
#endif

typedefstruct_container
{
charmember_0;
intmember_1;
charmember_2;
}container;

intmain(void)
{
container*a=NULL;
containerb={'a',2,'b'};

/*member_1在實(shí)例結(jié)構(gòu)體中的地址結(jié)構(gòu)體類型成員名*/
a=container_of(&b.member_1,container,member_1);
printf("a->member_0=%c
",a->member_0);
printf("a->member_1=%d
",a->member_1);
printf("a->member_2=%c
",a->member_2);

return0;
}

輸出:

75c25a34-4f09-11ee-a25d-92fbcf53809c.png


聲明:本文內(nèi)容及配圖由入駐作者撰寫(xiě)或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問(wèn)題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • Linux
    +關(guān)注

    關(guān)注

    87

    文章

    11123

    瀏覽量

    207916
  • 源碼
    +關(guān)注

    關(guān)注

    8

    文章

    626

    瀏覽量

    28971
  • 結(jié)構(gòu)體
    +關(guān)注

    關(guān)注

    1

    文章

    127

    瀏覽量

    10800

原文標(biāo)題:container_of()宏,太妙了~

文章出處:【微信號(hào):嵌入式情報(bào)局,微信公眾號(hào):嵌入式情報(bào)局】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。

收藏 人收藏

    評(píng)論

    相關(guān)推薦

    Linux內(nèi)核中container_of原理詳解

    Linux內(nèi)核中經(jīng)??梢?jiàn)container_of的身影,它在實(shí)際驅(qū)動(dòng)的編寫(xiě)中也是廣泛應(yīng)用。
    發(fā)表于 07-14 15:19 ?255次閱讀
    Linux內(nèi)核中<b class='flag-5'>container_of</b>原理詳解

    詳細(xì)聊聊container_of這個(gè)定義

    大家周末好,我是bug菌~ 今天主要是跟大家詳細(xì)聊聊container_of這個(gè)定義,非常經(jīng)典的,只是一直沒(méi)有抽時(shí)間細(xì)細(xì)品味,今天就跟大家一起來(lái)看看有何神奇之處。
    的頭像 發(fā)表于 11-13 09:45 ?563次閱讀

    揭開(kāi)linux內(nèi)核中container_of的神秘面紗

    在linux 內(nèi)核中有一個(gè)大名鼎鼎的container_of(),這個(gè)是用來(lái)干嘛的呢?我們先來(lái)看看它在內(nèi)核中是怎樣定義的。呵呵,乍一看不知道是什么東東。我們先來(lái)分析一下container_
    發(fā)表于 11-11 10:02

    offsetofcontainer_of詳解

    offsetofcontainer_of詳解 1.offsetofcontainer_of
    發(fā)表于 10-13 16:35

    Labview Active Container引用AUTODESK控件后異常?

    使用Labview active container引用后,單個(gè)VI運(yùn)行是正常的,單將單個(gè)VI引入后,出現(xiàn)異常,這種問(wèn)題需要怎樣解決,有相關(guān)經(jīng)驗(yàn)的人沒(méi)。
    發(fā)表于 05-19 18:31

    鴻蒙應(yīng)用開(kāi)發(fā)-container動(dòng)漫效果體驗(yàn)

    `container案例練習(xí)。 點(diǎn)擊按鈕觸發(fā)事件,兩個(gè)方塊顏色發(fā)生漸變。 Hml代碼如下:<!-- xxx.hml --><div class
    發(fā)表于 04-09 16:37

    Linux內(nèi)核中的C語(yǔ)言語(yǔ)法擴(kuò)展

    收集一些感覺(jué)比較好的博客鏈接,方便以后再看Linux 內(nèi)核中的 C 語(yǔ)言語(yǔ)法擴(kuò)展Linux 內(nèi)核驅(qū)動(dòng)中的指定初始化宏構(gòu)造利器:語(yǔ)句表達(dá)式Linux 內(nèi)核第一container_of零長(zhǎng)
    發(fā)表于 12-15 06:04

    請(qǐng)教一下大神內(nèi)核源碼中的containerof該怎樣去實(shí)現(xiàn)呢

    內(nèi)核中源碼是這樣的#define container_of(ptr, type, member) ({\ const typeof( ((type *)0)->member ) *__mptr
    發(fā)表于 05-07 11:00

    RT-Thread中侵入式鏈表的應(yīng)用有哪些呢

    rt_container_of(ptr, type, member)((type *)((char *)(ptr) - (unsigned long)(&((type *)0)->member)))具體的解析參見(jiàn):list_entry/
    發(fā)表于 12-05 13:59

    Linux內(nèi)核基礎(chǔ)-container_of

    TYPE是某struct的類型,0是一個(gè)假想TYPE類型struct,MEMBER是該struct中的一個(gè)成員。 由于該struct的基地址為0, MEMBER的地址就是該成員相對(duì)與struct頭地址的偏移量。
    發(fā)表于 05-14 14:26 ?815次閱讀

    Accelerated Container Image基于塊設(shè)備的容器鏡像加速服務(wù)

    ./oschina_soft/accelerated-container-image.zip
    發(fā)表于 05-10 11:15 ?0次下載
    Accelerated <b class='flag-5'>Container</b> Image基于塊設(shè)備的容器鏡像加速服務(wù)

    container-diff容器鏡像分析對(duì)比工具

    ./oschina_soft/container-diff.zip
    發(fā)表于 05-11 10:35 ?0次下載
    <b class='flag-5'>container</b>-diff容器鏡像分析對(duì)比工具

    Ansible Container容器自動(dòng)化構(gòu)建部署工具

    ./oschina_soft/ansible-container.zip
    發(fā)表于 05-11 10:15 ?1次下載
    Ansible <b class='flag-5'>Container</b>容器自動(dòng)化構(gòu)建部署工具

    Missing Container Metrics容器指標(biāo)收集工具

    ./oschina_soft/missing-container-metrics.zip
    發(fā)表于 05-12 14:24 ?1次下載
    Missing <b class='flag-5'>Container</b> Metrics容器指標(biāo)收集工具

    Linux內(nèi)核中的/container_of分析

    今天在看平臺(tái)設(shè)備實(shí)現(xiàn)的時(shí)候,看到to_xxx開(kāi)頭的“函數(shù)”。包括在內(nèi)核中也有很多此類的“函數(shù)”,其實(shí)他們都是container_of。因?yàn)閮?nèi)核是鏈表和結(jié)構(gòu)體的世界,因此內(nèi)核中有大量需求要 根據(jù)結(jié)構(gòu)體成員獲取結(jié)構(gòu)體地址 ,或者根據(jù)結(jié)構(gòu)體類型和結(jié)構(gòu)體成員類型獲取成員在結(jié)構(gòu)
    發(fā)表于 06-23 14:26 ?297次閱讀
    Linux內(nèi)核中的<b class='flag-5'>宏</b>/<b class='flag-5'>container_of</b>分析