如何从 C 中的成员访问包含结构?

How to access containing structure from a member in C?

我正在使用一些内核模块 (4.19.97),我分配 struct my_sock 如下所示。

struct my_target {
    union thingA { ... } a;
    struct thingB *b;
};

struct my_sock {
    struct sock sk;
    // ...
    struct my_target target;
};

struct my_sock *my_s;

my_s = my_sock_alloc();
// ...
my_s->sk.sk_prot->init(sk);

上面调用了这个回调。

static int my_init(struct sock *sk)
{   
    // I do the following because I cannot pass in the allocated 
    // `struct my_sock` into this function.
    struct my_sock *ms = my_sk(sk);

    // I want to access my_s->my_target or any field within 
    // `struct my_target` here, but at this point, `ms` is 
    // pointing to the the first member of `struct my_sock`, and 
    // not the originally allocated `my_s`.
    ms->target.a;
}

static inline struct my_sock* my_sk(const struct sock *s)
{
    return container_of(s, struct my_sock, sk);
}

// Here's how my_s gets allocated. Note that this is not the same
// structure as the first member of `struct my_sock`.
struct my_sock* my_sock_alloc(void)
{
    struct my_sock *sk = NULL;

    sk = kmem_cache_zalloc(my_sk_cachep, GFP_KERNEL);

    if (!sk)
        return NULL;

    return sk;
}

这就是问题所在。根据评论,内核在 include/linux/kernel.h 中具有 container_of 的代码,其中 casts a member of a structure out to the containing structure

当我使用my_sk(sk)时,我得到了包含结构的第一个成员的指针地址。问题是这与我在第一行分配的 my_s 不同,我需要指向 my_s 的指针才能访问 target 成员。

关于我如何在调用 my_init() 中访问 my_s->target 的想法(而不是全局化)?

由于 skstruct my_sock 中的第一个字段,您只需转换指针即可,一切正常:

struct my_sock *ms = (struct my_sock *)sk;

仅当“基础”结构不是第一个字段时才需要在container_of中完成的额外工作。