【发布时间】: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