【问题标题】:How to access containing structure from a member in C?如何从 C 中的成员访问包含结构?
【发布时间】:2020-12-16 19:41:30
【问题描述】:

我正在使用一些内核模块 (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 的想法(而不是使事情全局化)?

【问题讨论】:

  • my_a 是什么,应该是my_s 吗?你在哪里声明和分配sk
  • 你还没有展示你是如何设置sk的。这很可能是问题所在。
  • 应该是my_s->sk.sk_prot->init(my_s->sk);
  • my_s->sk.sk_prot->init(&my_s->sk);
  • container_of(s, struct my_sock, sk) 仅在您传递指向 my_sock 结构的 sk 成员的 sk 指针时有效。

标签: c linux sockets linux-kernel


【解决方案1】:

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

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

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

【讨论】:

  • 但它仍然可以工作,因为offsetof() 将是0
  • 有风险的。如果结构被编辑,这种方法可能会中断。
  • 同意@nicomp,应该始终使用container_of()
猜你喜欢
  • 2010-09-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-11-30
相关资源
最近更新 更多