日本免费高清视频-国产福利视频导航-黄色在线播放国产-天天操天天操天天操天天操|www.shdianci.com

學無先后,達者為師

網站首頁 編程語言 正文

Linux內核中container_of宏定義講解

作者:程序員李哈 更新時間: 2022-08-13 編程語言

在Linux內核中經常能在list_head雙向鏈表和socket等等操作中看到使用container_of宏定義來取到具體的結構體。

?當然第一眼看到的時候就會覺得這是啥?這又是啥?這什么東西?為什么通過這個可以拿到結構體的基地址?

問題不大,筆者會用此文章+畫圖的方法來仔細講解container_of宏定義。

?那么,用一個列子+畫圖來理解把。

在struct-A結構體中,存在幾個變量,包括struct-B。當我們已知struct-B的絕對地址時,此時需要得到struct-A的絕對地址,是不是就可以用struct-B的絕對地址 - struct-B前面的變量大小 = struct-A的絕對地址。?如下圖所示:

此時,有一個很愚蠢的方法,就是硬生生的減去上面變量的大小,就可以得到struct-A的基地址,但是如果之前有很多很多變量呢?所以此方法肯定是行不通的。

而內核使用的是0地址的騷操作來得到前面的變量的大小,虛擬出一個從0開始的內存,在內存中放入struct-A結構體,得到struct-B的偏移量。此時struct-B的偏移量就是前面變量的總大小。

用struct-B的絕對地址 - struct-B在0地址的偏移量 = struct-A的基址。?

我們再來看看container_of宏定義的源碼。

// ptr 已知的字段的地址
// type 結構體
// member 已經字段的字段名
#define container_of(ptr, type, member) ({                      \
		        const typeof( ((type *)0)->member ) *__mptr = (ptr);    \
			        (type *)( (char *)__mptr - offsetof(type,member) );})



// TYPE結構體
// MEMBER已知字段的字段名
#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)

container_of參數

????????// ptr 已知的字段的地址
????????// type 結構體
????????// member 已知的字段的字段名

offsetof參數

????????// TYPE 結構體
????????// MEMBER 已知的字段的字段名

  1. ?先把已知字段的地址轉換成具體的結構體中變量的類型(因為此方法在內核任意地方使用)。
  2. 把地址類型轉換成char*來解釋,因為offsetof算出來的是基于0地址的偏移量,所以必須要用char*來解釋(因為地址-1,代表減去地址所對應的類型個大小的內存單元)。
  3. offsetof算出基于0地址的偏移量。
  4. 絕對地址 - 偏移地址 = 結構體的首地址。
  5. 再轉換成結構體的指針來解釋這段內存空間。

總結:

最后,如果本帖對您有一定的幫助,希望能點贊+關注+收藏!您的支持是給我最大的動力,后續會一直更新各種框架的使用和框架的源碼解讀~!

原文鏈接:https://blog.csdn.net/qq_43799161/article/details/126223620

欄目分類
最近更新