我正在尝试理解linux内核网络代码,我遇到了很多函数,比如
static inline struct tcp_sock *tcp_sk(const struct sock *sk)
{
return (struct tcp_sock *)sk;
}
结构sock
和tcp_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>
谢谢。
答案 0 :(得分:3)
由于构造只是一个强制转换,所以没有任何东西被映射到#34;,sk
指向的内存位置实际上没有任何变化。
这仅适用于结构相似或至少以相同偏移的相同字段开头的情况。
在Linux内核代码中,您可以看到struct sock
和struct 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_sock
有struct 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
结构。