如何将一个结构映射到另一个结构,例如“return(struct a *)b”

时间:2016-07-05 11:11:55

标签: c struct linux-kernel kernel

我正在尝试理解linux内核网络代码,我遇到了很多函数,比如

static inline struct tcp_sock *tcp_sk(const struct sock *sk)
{
        return (struct tcp_sock *)sk;
}

结构socktcp_sock的内容完全不同。这种映射是如何完全发生的?具有相同名称和类型的结构成员是否相互映射?

修改1:更具体地说,在函数tcp_v4_connect

struct tcp_sock *tp = tcp_sk(sk);
tp->write_seq = secure_tcp_sequence_number(inet->inet_saddr,
                           inet->inet_daddr,
                           inet->inet_sport,
                           usin->sin_port);
err = tcp_connect(sk);

然后在上面调用的函数tcp_connect

struct tcp_sock *tp = tcp_sk(sk);
tcp_init_nondata_skb(buff, tp->write_seq++, TCPHDR_SYN);

变量write_seq仅存在于struct tcp_sock中,那么当只有tcp_connect传递给它时,它的值是如何传递给函数struct sock *sk的? / p>

谢谢。

2 个答案:

答案 0 :(得分:3)

由于构造只是一个强制转换,所以没有任何东西被映射到#34;,sk指向的内存位置实际上没有任何变化。

这仅适用于结构相似或至少以相同偏移的相同字段开头的情况。

在Linux内核代码中,您可以看到struct sockstruct tcp_sock共享struct sock的所有字段(tcp_sock包含inet_connection_sock,其中包含inet_sock一个sock,其中分别包含struct sock作为第一个元素。所以," 结构的内容......是完全不同的",并不完全正确。它们实际上是相同的(至少是struct sock的大小。)

为了能够正确地做到这一点,系统以某种方式必须知道"它可以安全地将struct tcp_sock转换为struct sock - 此信息通常隐藏在公共标题中的某个位置,在本例中位于sk_family部分(我最近没有检查过) ,但我猜这里的信息在sk

编辑后:

实际传递给您的函数的是指向内存区域的指针。无论以前做过什么都是由演员没有改变(如上所述)。如果我们可以安全地假设struct tcp_sock在某个时间之前是struct sock的指针,我们可以安全地将其重新投射到这样的野兽身上。这通常在代码中完成,该代码围绕具有泛型特定部分的数据(如本例中所示)。所有套接字(TCP,UDP,通用,Unix套接字......)数据都具有在所有特定套接字结构的开头的struct sock中收集的公共数据。因此,对于传入的套接字数据,该结构的所有通用部分首先由处理switch...case的函数处理,稍后必须有一些查看特定部分的大layered,然后传递一个特定的指针类型。

这允许struct sock编程方法,其中所有内容都首先被转换为通用struct sock,然后通用部分由所有套接字类型共有的函数处理,稍后,指针被回送它最初是,具体部分由专业人员处理。一直以来,基本上用作"背包的记忆区域"在where上保留特定数据只是保持不变。

答案 1 :(得分:3)

具有相同名称和类型的结构成员是否相互映射?

没有

struct sock sk; /* our sock struct */
struct tcp_sock *tcp_sk = (struct tcp_sock *)&sk;

tcp_sk指针现在只指向&sk指向的内存。现在,通过访问tcp_sk字段,您将访问分配给此指针的内存,但为了获得预期结果,存储在两个地址的数据应该有效。

现在,struct sock(套接字的网络层表示)具有s truct sock_common,因为它是第一个成员:

306 struct sock {
307         /*
308          * Now struct inet_timewait_sock also uses sock_common, so please just
309          * don't add nothing before this first member (__sk_common) --acme
310          */
311         struct sock_common      __sk_common;

struct tcp_sockstruct inet_connection_sock,因为它是第一个成员

struct tcp_sock {
138         /* inet_connection_sock has to be the first member of tcp_sock */
139         struct inet_connection_sock     inet_conn;

这个结构有struct inet_sock,因为它是第一个成员:

 90 struct inet_connection_sock {
 91         /* inet_sock has to be the first member! */
 92         struct inet_sock          icsk_inet;

猜猜结构是inet_sock的第一个成员......它是struct sock

172 struct inet_sock {
173         /* sk and pinet6 has to be the first two members of inet_sock */
174         struct sock             sk;

因此,访问tcp_sk.inet_conn.icsk_inet.sk您正在访问我们的sock结构。