给定指向本身是指针类型的成员的指针时,内核函数获取容器指针?

时间:2018-10-13 05:37:53

标签: c linux-kernel

当给定成员指针本身是指针类型时,我正在尝试访问结构容器。 container_of()在这种情况下不起作用,我必须手动计算偏移量,然后自己计算容器地址。我可以调用任何类似于container_of()的内核函数,但要注意这种情况吗?

例如下面的代码,

#include <stdio.h>
#include <string.h>
#include <stddef.h>
#define container_of(ptr, type, member) ({                      \
        const typeof( ((type *)0)->member ) *__mptr = (ptr);    \
        (type *)( (char *)__mptr - offsetof(type,member) );})

typedef struct A
{
    int filler;
    int *data;
}A;

int main(int argc, char *argv[])
{
    A *a = malloc(sizeof(A));
    a->data = malloc(sizeof(int));

    printf("1st part: use container_of():\n");
    printf("a: %p | a->data: %p\n", a, a->data);
    int *member_ptr = a->data;
    A *c = container_of(member_ptr, A, data);
    printf("c: %p\n", c);

    printf("2nd part: manually calculate offset: \n");
    unsigned long offset = (unsigned long)(&(((A*)0)->data));
    printf("a: %p | &(a->data): %p | offset: 0x%x | &(a->data) - offset: %p", a, &(a->data), offset, (unsigned long)(&(a->data)) - offset);

    free(a->data);
    free(a);
    return 0;
}

使用container_of()时,第一部分指针c不等于a:

Use container_of():
a: 0x166d260 | a->data: 0x166d280
c: 0x166d278

第二部分效果很好

Manually calculate offset: 
a: 0x166d260 | &(a->data): 0x166d268 | offset: 0x8 | &(a->data) - offset: 0x166d260

1 个答案:

答案 0 :(得分:1)

您显然很错误地使用了它,这就是gcc(应该)向您发出incompatible-pointer-types警告的原因。

应该是

A *c = container_of(&a->data, A, data);

A *c = container_of(a->data, A, data);

a->data值和a的地址之间绝对没有没有关系。

(建议:注意警告(或使用-Werror进行编译,因此您别无选择)。