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
  1. #define?container_of(ptr,?type,?member)?({??????\??
  2. ????const?typeof(?((type?*)0)->member?)?*__mptr?=?(ptr);????\??
  3. ????(type?*)(?(char?*)__mptr?-?offsetof(type,member)?);})??

? ? 其實它的語法很簡單,只是一些指針的靈活應用,它分兩步:

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

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

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

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

[cpp] view plain copy
  1. /*?linux-2.6.38.8/include/linux/compiler-gcc4.h?*/??
  2. #define?__compiler_offsetof(a,b)?__builtin_offsetof(a,b)??
  3. ??
  4. /*?linux-2.6.38.8/include/linux/stddef.h?*/??
  5. #undef?offsetof??
  6. #ifdef?__compiler_offsetof??
  7. #define?offsetof(TYPE,MEMBER)?__compiler_offsetof(TYPE,MEMBER)??
  8. #else??
  9. #define?offsetof(TYPE,?MEMBER)?((size_t)?&((TYPE?*)0)->MEMBER)??
  10. #endif??
  11. ??
  12. #include?<stdio.h>??
  13. ??
  14. struct?test_struct?{??
  15. ????int?num;??
  16. ????char?ch;??
  17. ????float?fl;??
  18. };??
  19. ??
  20. int?main(void)??
  21. {??
  22. ????printf("offsetof(struct?test_struct,?num)?=?%d\n",???
  23. ????????????offsetof(struct?test_struct,?num));??
  24. ??????
  25. ????printf("offsetof(struct?test_struct,??ch)?=?%d\n",???
  26. ????????????offsetof(struct?test_struct,?ch));??
  27. ??????
  28. ????printf("offsetof(struct?test_struct,??fl)?=?%d\n",???
  29. ????????????offsetof(struct?test_struct,?fl));??
  30. ??????
  31. ????return?0;??
  32. }??

? ? 說明,__builtin_offsetof(a,b)是GCC的內置函數,可認為它的實現與((size_t) &((TYPE *)0)->MEMBER)這段代碼是一致的。

? ? 例子輸出結果:?

[cpp] view plain copy
  1. offsetof(struct?test_struct,?num)?=?0??
  2. offsetof(struct?test_struct,??ch)?=?4??
  3. 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
  1. /*?linux-2.6.38.8/include/linux/compiler-gcc4.h?*/??
  2. #define?__compiler_offsetof(a,b)?__builtin_offsetof(a,b)??
  3. ??
  4. /*?linux-2.6.38.8/include/linux/stddef.h?*/??
  5. #undef?offsetof??
  6. #ifdef?__compiler_offsetof??
  7. #define?offsetof(TYPE,MEMBER)?__compiler_offsetof(TYPE,MEMBER)??
  8. #else??
  9. #define?offsetof(TYPE,?MEMBER)?((size_t)?&((TYPE?*)0)->MEMBER)??
  10. #endif??
  11. ??
  12. /*?linux-2.6.38.8/include/linux/kernel.h?*?
  13. ?*?container_of?-?cast?a?member?of?a?structure?out?to?the?containing?structure?
  14. ?*?@ptr:?the?pointer?to?the?member.?
  15. ?*?@type:???the?type?of?the?container?struct?this?is?embedded?in.?
  16. ?*?@member:????the?name?of?the?member?within?the?struct.?
  17. ?*?
  18. ?*/??
  19. #define?container_of(ptr,?type,?member)?({??????\??
  20. ????const?typeof(?((type?*)0)->member?)?*__mptr?=?(ptr);????\??
  21. ????(type?*)(?(char?*)__mptr?-?offsetof(type,member)?);})??
  22. ??
  23. #include?<stdio.h>??
  24. ??
  25. struct?test_struct?{??
  26. ????int?num;??
  27. ????char?ch;??
  28. ????float?fl;??
  29. };??
  30. ??
  31. int?main(void)??
  32. {??
  33. ????struct?test_struct?init_test_struct?=?{?99,?'C',?59.12?};??
  34. ??
  35. ????char?*char_ptr?=?&init_test_struct.ch;??
  36. ??
  37. ????struct?test_struct?*test_struct?=?container_of(char_ptr,?struct?test_struct,?ch);??
  38. ??????
  39. ????printf("?test_struct->num?=?%d\n?test_struct->ch?=?%c\n?test_struct->fl?=?%f\n",???
  40. ????????test_struct->num,?test_struct->ch,?test_struct->fl);??
  41. ??????
  42. ????return?0;??
  43. }??

? ? 例子輸出結果:?

[cpp] view plain copy
  1. test_struct->num?=?99??
  2. test_struct->ch?=?C??
  3. test_struct->fl?=?59.119999??

? ? 不適當的例子,如清單3:?

[cpp] view plain copy
  1. /*?linux-2.6.38.8/include/linux/compiler-gcc4.h?*/??
  2. #define?__compiler_offsetof(a,b)?__builtin_offsetof(a,b)??
  3. ??
  4. /*?linux-2.6.38.8/include/linux/stddef.h?*/??
  5. #undef?offsetof??
  6. #ifdef?__compiler_offsetof??
  7. #define?offsetof(TYPE,MEMBER)?__compiler_offsetof(TYPE,MEMBER)??
  8. #else??
  9. #define?offsetof(TYPE,?MEMBER)?((size_t)?&((TYPE?*)0)->MEMBER)??
  10. #endif??
  11. ??
  12. /*?linux-2.6.38.8/include/linux/kernel.h?*?
  13. ?*?container_of?-?cast?a?member?of?a?structure?out?to?the?containing?structure?
  14. ?*?@ptr:?the?pointer?to?the?member.?
  15. ?*?@type:???the?type?of?the?container?struct?this?is?embedded?in.?
  16. ?*?@member:????the?name?of?the?member?within?the?struct.?
  17. ?*?
  18. ?*/??
  19. #define?container_of(ptr,?type,?member)?({??????\??
  20. ????const?typeof(?((type?*)0)->member?)?*__mptr?=?(ptr);????\??
  21. ????(type?*)(?(char?*)__mptr?-?offsetof(type,member)?);})??
  22. ??
  23. #include?<stdio.h>??
  24. ??
  25. struct?test_struct?{??
  26. ????int?num;??
  27. ????char?ch;??
  28. ????float?fl;??
  29. };??
  30. ??
  31. int?main(void)??
  32. {??
  33. ????char?real_ch?=?'A';??
  34. ????char?*char_ptr?=?&real_ch;??
  35. ??
  36. ????struct?test_struct?*test_struct?=?container_of(char_ptr,?struct?test_struct,?ch);??
  37. ??
  38. ????printf("?char_ptr?=?%p??test_struct?=?%p\n\n",?char_ptr,?test_struct);??
  39. ??
  40. ????printf("?test_struct->num?=?%d\n?test_struct->ch?=?%c\n?test_struct->fl?=?%f\n",???
  41. ????????test_struct->num,?test_struct->ch,?test_struct->fl);??
  42. ??????
  43. ????return?0;??
  44. }??

? ? 例子輸出結果:?

[cpp] view plain copy
  1. char_ptr?=?0xbfb72d7f??test_struct?=?0xbfb72d7b??
  2. ??
  3. test_struct->num?=?-1511000897??
  4. test_struct->ch?=?A??
  5. test_struct->fl?=?0.000000??

? ? 注意,由于這里并沒有一個具體的結構體變量,所以成員num和fl的值是不確定的。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/452919.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/452919.shtml
英文地址,請注明出處:http://en.pswp.cn/news/452919.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

mysql concat例子_MYSQL中CONCAT詳解

concat()函數1. 功能&#xff1a;返回結果為連接參數產生的字符串。如有任何一個參數為NULL &#xff0c;則返回值為 NULL。2. 語法concat(str1, str2,...)3. 例子案例一&#xff1a;mysql> select concat(蘋果,香蕉,梨子);------------------------------| CONCAT(蘋果,香蕉…

常見的狀態響應碼

200&#xff1a;請求正常&#xff0c;服務器正常的返回數據 301&#xff1a;永久重定向。比如在訪問www.jingdong.com的時候&#xff0c;會重定向到www.jd.com。 302&#xff1a;臨時重定向。比如在訪問一個需要登錄的界面時&#xff0c;而此時沒有登錄&#xff0c;那么就會重定…

軟件行業為什么那么多項目經理

記得聽誰說過&#xff0c;軟件行業的項目經理太濫了&#xff0c;二十幾歲的毛頭小伙子&#xff0c;動不動就是項目經理&#xff0c;手下沒幾個人&#xff0c;管的也沒幾個事&#xff0c;在其他行業&#xff0c;項目經理一般都是四五十歲的老頭子做&#xff0c;要聯系這&#xf…

ipv6的表示方法

v冒分十六進制表示法X:X:X:X:X:X:X:X 其中X表示地址中16位二進制數的十六進制值 例&#xff1a;FEDC:BA98:7654:3210:FEDC:BA98:7654:3210 v零壓縮法如其中有多個連續的零&#xff0c;則可用零壓縮法 如 &#xff1a;1080:0000:0000:0000:0008:0800:200C:417A 可寫成&am…

mysql php7安裝配置_centos7無網絡下安裝部署php7.1.33+mysql5.7.28+apache2.4.6-Go語言中文社區...

centos7無網絡下安裝部署php7.1.33mysql5.7.28apache2.4.6一、1、先ping www.baidu.com&#xff0c;root賬戶下&#xff0c;如果未聯網&#xff0c;創建目錄&#xff0c;把提前下載好的rpm包拷貝到rpm目錄下如圖&#xff1a;(如果沒有安裝包請查看我的另一篇教程下載這些安裝包…

webkit渲染

2019獨角獸企業重金招聘Python工程師標準>>> 參考鏈接 理解WebKit和Chromium 簡明魔法學院 Chrome軟件渲染 WebKit渲染基礎 Webkit 渲染基礎 Webkit不是瀏覽器,它是一個渲染引擎 軟件渲染 硬件渲染(GPU加速) 會觸發GPU加速的屬性 CSS3 3D transformation, trans…

element ui中dialog相關問題

一&#xff0c;今天需要在dialog里面引入另一個頁面&#xff0c;就是打開dialog顯示該頁面&#xff08;把頁面放到dialog中&#xff09;&#xff0c;引入的語句如下&#xff1a; <iframe src"view?pathrkdj_b" ></iframe> 二&#xff0c;使用table組件時…

數據結構與算法--4.使用堆棧模擬隊列

問題&#xff1a; 隊列的插入和刪除遵循先入先出的原則&#xff0c;而堆棧遵循后進先出的原則。用兩個堆棧模擬隊列&#xff0c;要求實現時不能分配超過O&#xff08;1&#xff09;的內存&#xff0c;時間復雜度必須是o&#xff08;m&#xff09;。 思路&#xff1a; 用兩個…

IT行業的你,在成本部門還是利潤部門

題外話&#xff1a;本文應該引起項目管理者和開發人員的思考&#xff1a;如何進行薪酬管理&#xff1f;如何規劃職業生涯&#xff1f; 生在IT行業&#xff0c;發現周圍很多朋友對薪酬問題有疑問&#xff0c;因為這種不解&#xff0c;導致經常帶情緒&#xff0c;對工作、生活很…

ipv4到ipv6的過渡

v雙協議站&#xff1a;過渡時期&#xff0c;站點必須同時支持IPv4和IPv6v隧道技術&#xff1a;IPv6主機之間通信必須使用IPv4的隧道v首部轉換&#xff1a;用于發送方使用IPv6&#xff0c;而接收方使用IPv4

關于爬蟲中常見的兩個網頁解析工具的分析 —— lxml / xpath 與 bs4 / BeautifulSoup...

http://www.cnblogs.com/binye-typing/p/6656595.html 讀者可能會奇怪我標題怎么理成這個鬼樣子&#xff0c;主要是單單寫 lxml 與 bs4 這兩個 py 模塊名可能并不能一下引起大眾的注意&#xff0c;一般講到網頁解析技術&#xff0c;提到的關鍵詞更多的是 BeautifulSoup 和 xpat…

java如何去掉html標簽_Java后端去掉HTML標簽獲取純文本-Fun言

今天又對我的博客首頁進行了一次版本的更新&#xff0c;使其自適應屏幕&#xff0c;獲得更好的用戶體驗&#xff0c;然后就出現點小問題&#xff0c;那就是原來的摘要是人為添加的&#xff0c;有長有短&#xff0c;對自適應屏幕有影響&#xff0c;所以我們現在是截取文章的前20…

單/雙中括號與測試條件

測試命令 tesst[]內置命令[[]]bash中的關鍵字 單中括號 格式[#express1#op#express2#] 注意&#xff1a;   其中#代表括號不能省略   不能匹配模式   變量引用應用雙引號括起&#xff0c;尤其當變量引用有空格時   與或非形式-a –o -not   常量應用單/雙引號括起  …

暗時間--平凡與優秀間的距離

每個人都希望&#xff0c;在他所從事的領域很優秀&#xff0c;那么如何才能優秀呢&#xff1f;有人做過一個研究&#xff0c;說那些優秀的音樂家&#xff0c;在他們成名之前&#xff0c;已經訓練過10000小時。有人可能成功得早&#xff0c;如莫扎特16歲&#xff0c;有些可能需要…

IP分組

IP分組就是根據Ip地址來進行分組&#xff0c;目的可以是為了對不同 的地址組分配不同的帶寬&#xff08;限速&#xff09;配置地址組時&#xff0c;其輸入格式為A.B.C.D-A.B.C.E&#xff0c;例如&#xff1a;192.168.1.1-192.168.1.250

python3基礎3--數據類型--數據運算--表達式if -else-while-for

一、python3 數據類型 1.1 數字例如&#xff1a;1,2,3,4等1.2 int&#xff08;整型&#xff09; 在32位機器上&#xff0c;整數的位數為32位&#xff0c;取值范圍為-2**31&#xff5e;2**31-1&#xff0c;即-2147483648&#xff5e;2147483647在64位系統上&#xff0c;整數的位…

spark java教程_(Spark)學習進度十四(Spark之Java獨立應用編程)

環境如下:(更新了林子雨教程中不可使用的部分) Hadoop 2.6.0以上 java JDK 1.7以上 Spark 3.0.0-preview2 二、java獨立應用編程(在下載依賴jar包的過程中如遇到卡頓現象可以Ctrl+C停止下載,然后重新執行本條命令即可繼續下載相應的依賴jar包) 1、安裝maven ubuntu中沒有自帶…

nowcoderD Xieldy And His Password

題意:一個01序列,長度1e6,問有多少子串十進制是3的倍數 題解:DP[i][j]代表前i個并且以i為結尾,且十進制%3j的串的個數 #include<bits/stdc.h> #define maxn 1001000 using namespace std; char s[maxn]; long long dp[maxn][3], sum; int main(){while(~scanf("%s&q…

3D電視,你知道多少?

1.3D電視常見知識 系統概述篇 1、 什么是3D電視&#xff1f; 答&#xff1a;3D電視是一種能夠模擬實際景物的真實空間關系的新型電視&#xff0c;它利用人眼的視覺特性產生立體感&#xff0c;讓觀眾感受到觀看的影像是具有深度特性的三維立體場景&#xff0c;觀眾對延伸于屏幕…

testng.xml文件配置

TestNG的DTD檢查文件&#xff1a;http://testng.org/testng-1.0.dtd.php <?xml version"1.0" encoding"UTF-8"?> <!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd"> <!--suite&#xff08;測試套件&#xff09;為根…