4.2 container_of的書寫
在對(duì)內(nèi)核的理解上沒有所謂的捷徑,該花多少時(shí)間,該花多少精力,它就是應(yīng)當(dāng)要花到相當(dāng)?shù)某潭炔拍墚a(chǎn)生理解。而且不應(yīng)放過每一個(gè)細(xì)節(jié),因?yàn)椴荒芾斫馔且恍┘?xì)節(jié)沒有做到極致。
近來我發(fā)覺到linux內(nèi)核對(duì)container_of有兩種不同的寫法,有一種版本是這樣寫的:
#define container_of(ptr, type, member) ({ ? ? ? ? ? ? ?\ ? ? ? ? const typeof( ((type *)0)->member ) *__mptr = (ptr); ? ?\ ? ? ? ? (type *)( (char *)__mptr - offsetof(type,member) );})
而另一種是這樣寫的:
#define container_of(ptr, type, member) ({ ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?\ ? ? ? ?void *__mptr = (void *)(ptr); ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? \ ? ? ? ?static_assert(__same_type(*(ptr), ((type *)0)->member) || ? ? ? \ ? ? ? ? ? ? ? ? ? ? ?__same_type(*(ptr), void), ? ? ? ? ? ? ? ? ? ? ? ?\ ? ? ? ? ? ? ? ? ? ? ?"pointer type mismatch in container_of()"); ? ? ? \ ? ? ? ?((type *)(__mptr - offsetof(type, member))); })
就實(shí)際效果而言,如果輸入規(guī)范的話,兩種書寫算式事實(shí)上都能返回到被認(rèn)為正確的結(jié)果。不過后一種還額外提供了一個(gè)檢查參數(shù)輸入是否得當(dāng)?shù)墓δ堋?/p>
它是通過利用__same_type(type1,type2)結(jié)合static_assert(expr,msg)表達(dá)式,如果出現(xiàn)判斷type1和type2類型不相同,則_same_type(type1,type2)等于0,這將導(dǎo)致static_assert(expr,msg)中的expr表示為0,那么在編譯的階段(還沒到代碼運(yùn)行),編譯器就會(huì)報(bào)出“Static error”并輸出"msg"的信息。
在這里它要求ptr必須是member類型的指針,或者說ptr是一個(gè)空類型,否則就會(huì)校驗(yàn)出類型不匹配的錯(cuò)誤信息:“pointer type mismatch in container_of()”
這給因使用container_of導(dǎo)致的錯(cuò)誤提供了一個(gè)檢測接口。