內核 宏定義 container_of

container_of

1.1 container_of介紹

定義:container_of在linux內核的include/linux/kernel.h中定義。

#define container_of(ptr, type, member) ({          \
    const typeof( ((type *)0)->member ) *__mptr = (ptr);    \
    (type *)( (char *)__mptr - offsetof(type,member) );})

說明:根據"結構體(type)變量"中的"域成員變量(member)的指針(ptr)"來獲取指向整個結構體變量的指針。
(01) typeof( ( (type *)0)->member )     取出member成員的變量類型。
(02) const typeof( ((type *)0)->member ) *__mptr = (ptr)    定義變量__mptr指針,並將ptr賦值給__mptr。經過這一步,__mptr爲member數據類型的常量指針,其指向ptr所指向的地址。
(04) (char *)__mptr    將__mptr轉換爲字節型指針。
(05) offsetof(type,member))    就是獲取"member成員"在"結構體type"中的位置偏移。
(06) (char *)__mptr - offsetof(type,member))    就是用來獲取"結構體type"的指針的起始地址(爲char *型指針)。
(07) (type *)( (char *)__mptr - offsetof(type,member) )    就是將"char *類型的結構體type的指針"轉換爲"type *類型的結構體type的指針"。

1.2 container_of示例

代碼(containerof_test.c)

#include <stdio.h>
#include <string.h>

// 獲得結構體(TYPE)的變量成員(MEMBER)在此結構體中的偏移量。
#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)

// 根據"結構體(type)變量"中的"域成員變量(member)的指針(ptr)"來獲取指向整個結構體變量的指針
#define container_of(ptr, type, member) ({          \
    const typeof( ((type *)0)->member ) *__mptr = (ptr);    \
    (type *)( (char *)__mptr - offsetof(type,member) );})

struct student
{
    char gender;
    char sex[20];
    int age;
    char name[20];
};

void main()
{
    struct student stu;
    struct student *pstu;

    stu.gender = '1';
    strcpy(stu.sex, "boy");
    stu.age = 24;
    strcpy(stu.name, "caoft");

    // 根據"id地址" 獲取 "結構體的地址"。
    pstu = container_of(&stu.sex, struct student, sex);

    // 根據獲取到的結構體student的地址,訪問其它成員
    printf("gender= %c\n", pstu->gender);
    printf("age= %d\n", pstu->age);
    printf("name= %s\n", pstu->name);
}

結果

 

1.3 container_of圖解

type是結構體,它代表"整體";而member是成員,它是整體中的某一部分,而且member的地址是已知的。
將offsetof看作一個數學問題來看待,問題就相當簡單了:已知'整體'和該整體中'某一個部分',要根據該部分的地址,計算出整體的地址。

 

巨人的肩膀:

https://www.cnblogs.com/skywang12345/p/3562146.html

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章