麻豆小视频在线观看_中文黄色一级片_久久久成人精品_成片免费观看视频大全_午夜精品久久久久久久99热浪潮_成人一区二区三区四区

首頁 > 學院 > 開發設計 > 正文

理解Linux contain_of()宏

2019-11-06 09:23:11
字體:
來源:轉載
供稿:網友

linux contain_of()宏

container_of()函數

1.該宏定義在include/linux/kernel.h中

439/**

440 * container_of - cast a member of a structure out to the containing structure

441 * @ptr:        the pointer to the member.

442 * @type:       the type of theContainer struct this is embedded in.

443 * @member:     the name of the member within the struct.

444 *

445 */

446 #define container_of(ptr, type, member) ({                      /

447        const typeof( ((type *)0)->member ) *__mptr = (ptr);    /

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

它的作用顯而易見,那就是根據一個結構體變量中的一個域成員變量的指針來獲取指向整個結構體變量的指針。比如,有一個結構體變量,其定義如下:

struct demo_struct {

          type1 member1;

           type2 member2;

           type3 member3;

           type4 member4;

      };

     struct demo_struct demo;

同時,在另一個地方,獲得了變量demo中的某一個域成員變量的指針,比如:

type3  *memp = get_member_pointer_from_somewhere();

此時,如果需要獲取指向整個結構體變量的指針,而不僅僅只是其某一個域成員變量的指針,我們就可以這么做:

struct demo_struct *demop = container_of(memp, struct demo_struct, member3);

這樣,我們就通過一個結構體變量的一個域成員變量的指針獲得了整個結構體變量的指針。

下面說一說我對于這個container_of的實現的理解:

首先,我們將container_of(memp, struct demo_struct, type3)根據宏的定義進行展開如下:

struct demo_struct *demop = ({                      /

const typeof( ((struct demo_struct *)0)->member3 ) *__mptr = (memp);    /

(struct demo_struct *)( (char *)__mptr - offsetof(struct demo_struct, member3) );})

其中,typeof是GNU C對標準C的擴展,它的作用是根據變量獲取變量的類型。因此,上述代碼中的第2行的作用是首先使用typeof獲取結構體域變量member3的類型為 type3,然后定義了一個type3指針類型的臨時變量__mptr,并將實際結構體變量中的域變量的指針memp的值賦給臨時變量__mptr。

(char *)__mptr轉換為字節型指針。(char *)__mptr - offsetof(type,member) )用來求出結構體起始地址(為char *型指針),然后(type *)( (char *)__mptr - offsetof(type,member) )在(type *)作用下進行將字節型的結構體起始指針轉換為type *型的結構體起始指針。

 

假設結構體變量demo在實際內存中的位置如下圖所示:

     demo

 +-------------+ 0xA000

 |   member1   |

 +-------------+ 0xA004

 |   member2   |

 +-------------+ 0xA010

 |   member3   |

 +-------------+ 0xA018

 |   member4   |

 +-------------+

 

則,在執行了上述代碼的第2行之后__mptr的值即為0xA010。

 

再看上述代碼的第3行,其中需要說明的是offsetof,它定義在include/linux/stddef.h中,其定義如下:

1.#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)

先分析一下這個宏的運行機理:

一共4步

1. ( (TYPE *)0 ) 將零轉型為TYPE類型指針;

2. ((TYPE *)0)->MEMBER 訪問結構中的數據成員;

3. &( ( (TYPE *)0 )->MEMBER )取出數據成員的地址;

4.(size_t)(&(((TYPE*)0)->MEMBER))結果轉換類型。巧妙之處在于將0轉換成(TYPE*),結構以內存空間首地址0作為起始地址,則成員地址自然為偏移地址;

 

同樣,我們將上述的offsetof調用展開,即為:

1. (struct demo_struct *)( (char *)__mptr - ((size_t) &((struct demo_struct *)0)->member3) );

可見,offsetof的實現原理如上所述,就是取結構體中的域成員相對于地址0的偏移地址,也就是域成員變量相對于結構體變量首地址的偏移。

 

因此,offsetof(struct demo_struct, member3)調用返回的值就是member3相對于demo變量的偏移。結合上述給出的變量地址分布圖可知,offsetof(struct demo_struct, member3)將返回0x10。

 

于是,由上述分析可知,此時,__mptr==0xA010,offsetof(struct demo_struct, member3)==0x10。

因此, (char *)__mptr - ((size_t) &((struct demo_struct *)0)->member3) == 0xA010 - 0x10 == 0xA000,也就是結構體變量demo的首地址(如上圖所示)。

 

這就是從結構體某成員變量指針來求出該結構體的首指針。指針類型從結構體某成員變量類型轉換為該結構體類型。

由此,container_of實現了根據一個結構體變量中的一個域成員變量的指針來獲取指向整個結構體變量的指針的功能。


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 蜜桃网站免费 | 91精品国产综合久久久动漫日韩 | freexxxhd喷水| 久草视频手机在线观看 | 欧美精品在线免费观看 | 国产精选久久久 | 免费观看9x视频网站在线观看 | 一级黄色欧美 | 国产一区精品在线观看 | 日产精品一区二区三区在线观看 | 99成人精品视频 | 国产交换3p国产精品 | 青草视频在线观看视频 | 黄色片免费在线播放 | 男人久久天堂 | 亚洲一区二区在线视频 | 日本va在线观看 | 亚洲最新黄色网址 | 成人午夜免费看 | 亚洲一级成人 | 国产精品欧美久久久久一区二区 | 久草视频国产在线 | 中文字幕免费看 | 深夜福利视频免费观看 | 国产精品九九久久一区hh | 国产精品视频一区二区三区四 | 日韩一级片一区二区三区 | 国产成人综合在线视频 | 青草久久久久 | 国产精品免费观在线 | 九九热精品在线播放 | 国产91小视频在线观看 | mmmwww| 中午字幕无线码一区2020 | 免费毛片小视频 | 久国产 | 亚洲一区二区三区视频免费 | 免费永久在线观看黄网 | 久久久精品视频免费看 | 国产精品18久久久久久久久 | 亚欧在线免费观看 |