日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > linux >内容正文

linux

Linux内核中的常用宏container_of其实很简单【转】

發布時間:2023/12/19 linux 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Linux内核中的常用宏container_of其实很简单【转】 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

轉自:http://blog.csdn.net/npy_lp/article/details/7010752

開發平臺:Ubuntu11.04

? ? 編 譯器:gcc version 4.5.2 (Ubuntu/Linaro4.5.2-8ubuntu4)

?

? ? Container_of在Linux內核中是一個常用的宏,用于從包含在某個結構中的指針獲得結構本身的指針,通俗地講就是通過結構體變量中某個成員的首地址進而獲得整個結構體變量的首地址。

? ? Container_of的定義如下:?

[cpp] view plain copy
  • #define?container_of(ptr,?type,?member)?({??????\??
  • ????const?typeof(?((type?*)0)->member?)?*__mptr?=?(ptr);????\??
  • ????(type?*)(?(char?*)__mptr?-?offsetof(type,member)?);})??
  • ? ? 其實它的語法很簡單,只是一些指針的靈活應用,它分兩步:

    ? ? 第一步,首先定義一個臨時的數據類型(通過typeof( ((type *)0)->member )獲得)與ptr相同的指針變量__mptr,然后用它來保存ptr的值。

    ? ? 第二步,用(char *)__mptr減去member在結構體中的偏移量,得到的值就是整個結構體變量的首地址(整個宏的返回值就是這個首地址)。

    ? ? 其中的語法難點就是如何得出成員相對結構體的偏移量?

    ? ? 通過例子說明,如清單1:?

    [cpp] view plain copy
  • /*?linux-2.6.38.8/include/linux/compiler-gcc4.h?*/??
  • #define?__compiler_offsetof(a,b)?__builtin_offsetof(a,b)??
  • ??
  • /*?linux-2.6.38.8/include/linux/stddef.h?*/??
  • #undef?offsetof??
  • #ifdef?__compiler_offsetof??
  • #define?offsetof(TYPE,MEMBER)?__compiler_offsetof(TYPE,MEMBER)??
  • #else??
  • #define?offsetof(TYPE,?MEMBER)?((size_t)?&((TYPE?*)0)->MEMBER)??
  • #endif??
  • ??
  • #include?<stdio.h>??
  • ??
  • struct?test_struct?{??
  • ????int?num;??
  • ????char?ch;??
  • ????float?fl;??
  • };??
  • ??
  • int?main(void)??
  • {??
  • ????printf("offsetof(struct?test_struct,?num)?=?%d\n",???
  • ????????????offsetof(struct?test_struct,?num));??
  • ??????
  • ????printf("offsetof(struct?test_struct,??ch)?=?%d\n",???
  • ????????????offsetof(struct?test_struct,?ch));??
  • ??????
  • ????printf("offsetof(struct?test_struct,??fl)?=?%d\n",???
  • ????????????offsetof(struct?test_struct,?fl));??
  • ??????
  • ????return?0;??
  • }??
  • ? ? 說明,__builtin_offsetof(a,b)是GCC的內置函數,可認為它的實現與((size_t) &((TYPE *)0)->MEMBER)這段代碼是一致的。

    ? ? 例子輸出結果:?

    [cpp] view plain copy
  • offsetof(struct?test_struct,?num)?=?0??
  • offsetof(struct?test_struct,??ch)?=?4??
  • offsetof(struct?test_struct,??fl)?=?8??
  • ? ? 其中代碼難以理解的地方就是它靈活地運用了0地址。如果覺得&( (struct test_struct *)0 )->ch這樣的代碼不好理解,那么我們可以假設在0地址分配了一個結構體變量struct test_struct a,然后定義結構體指針變量p并指向a(struct test_struct *p = &a),如此我們就可以通過&p->ch獲得成員ch的地址。由于a的首地址為0x0,所以成員ch的首地址為0x4。

    ?

    ? ? 最后通過強制類型轉換(size_t)把一個地址值轉換為一個整數。

    ? ? 分析完container_of的定義,接下來舉兩個例子來體會一下它的使用方法。

    ? ? 正確的例子,如清單2:?

    [cpp] view plain copy
  • /*?linux-2.6.38.8/include/linux/compiler-gcc4.h?*/??
  • #define?__compiler_offsetof(a,b)?__builtin_offsetof(a,b)??
  • ??
  • /*?linux-2.6.38.8/include/linux/stddef.h?*/??
  • #undef?offsetof??
  • #ifdef?__compiler_offsetof??
  • #define?offsetof(TYPE,MEMBER)?__compiler_offsetof(TYPE,MEMBER)??
  • #else??
  • #define?offsetof(TYPE,?MEMBER)?((size_t)?&((TYPE?*)0)->MEMBER)??
  • #endif??
  • ??
  • /*?linux-2.6.38.8/include/linux/kernel.h?*?
  • ?*?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)?);})??
  • ??
  • #include?<stdio.h>??
  • ??
  • struct?test_struct?{??
  • ????int?num;??
  • ????char?ch;??
  • ????float?fl;??
  • };??
  • ??
  • int?main(void)??
  • {??
  • ????struct?test_struct?init_test_struct?=?{?99,?'C',?59.12?};??
  • ??
  • ????char?*char_ptr?=?&init_test_struct.ch;??
  • ??
  • ????struct?test_struct?*test_struct?=?container_of(char_ptr,?struct?test_struct,?ch);??
  • ??????
  • ????printf("?test_struct->num?=?%d\n?test_struct->ch?=?%c\n?test_struct->fl?=?%f\n",???
  • ????????test_struct->num,?test_struct->ch,?test_struct->fl);??
  • ??????
  • ????return?0;??
  • }??
  • ? ? 例子輸出結果:?

    [cpp] view plain copy
  • test_struct->num?=?99??
  • test_struct->ch?=?C??
  • test_struct->fl?=?59.119999??
  • ? ? 不適當的例子,如清單3:?

    [cpp] view plain copy
  • /*?linux-2.6.38.8/include/linux/compiler-gcc4.h?*/??
  • #define?__compiler_offsetof(a,b)?__builtin_offsetof(a,b)??
  • ??
  • /*?linux-2.6.38.8/include/linux/stddef.h?*/??
  • #undef?offsetof??
  • #ifdef?__compiler_offsetof??
  • #define?offsetof(TYPE,MEMBER)?__compiler_offsetof(TYPE,MEMBER)??
  • #else??
  • #define?offsetof(TYPE,?MEMBER)?((size_t)?&((TYPE?*)0)->MEMBER)??
  • #endif??
  • ??
  • /*?linux-2.6.38.8/include/linux/kernel.h?*?
  • ?*?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)?);})??
  • ??
  • #include?<stdio.h>??
  • ??
  • struct?test_struct?{??
  • ????int?num;??
  • ????char?ch;??
  • ????float?fl;??
  • };??
  • ??
  • int?main(void)??
  • {??
  • ????char?real_ch?=?'A';??
  • ????char?*char_ptr?=?&real_ch;??
  • ??
  • ????struct?test_struct?*test_struct?=?container_of(char_ptr,?struct?test_struct,?ch);??
  • ??
  • ????printf("?char_ptr?=?%p??test_struct?=?%p\n\n",?char_ptr,?test_struct);??
  • ??
  • ????printf("?test_struct->num?=?%d\n?test_struct->ch?=?%c\n?test_struct->fl?=?%f\n",???
  • ????????test_struct->num,?test_struct->ch,?test_struct->fl);??
  • ??????
  • ????return?0;??
  • }??
  • ? ? 例子輸出結果:?

    [cpp] view plain copy
  • char_ptr?=?0xbfb72d7f??test_struct?=?0xbfb72d7b??
  • ??
  • test_struct->num?=?-1511000897??
  • test_struct->ch?=?A??
  • test_struct->fl?=?0.000000??
  • ? ? 注意,由于這里并沒有一個具體的結構體變量,所以成員num和fl的值是不確定的。

    總結

    以上是生活随笔為你收集整理的Linux内核中的常用宏container_of其实很简单【转】的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。