C 一个结构如何通过类似“的方式映射到另一个结构?”;返回(结构a*)b“;
我试图理解linux内核网络代码,我遇到了很多函数,比如C 一个结构如何通过类似“的方式映射到另一个结构?”;返回(结构a*)b“;,c,struct,linux-kernel,kernel,C,Struct,Linux Kernel,Kernel,我试图理解linux内核网络代码,我遇到了很多函数,比如 static inline struct tcp_sock *tcp_sk(const struct sock *sk) { return (struct tcp_sock *)sk; } 结构sock和tcp_sock的内容有很大不同。这种映射究竟是如何发生的?具有相同名称和类型的结构成员是否相互映射 编辑1:更具体地说,在函数tcp\u v4\u connect中 struct tcp_sock *tp = tcp_
static inline struct tcp_sock *tcp_sk(const struct sock *sk)
{
return (struct tcp_sock *)sk;
}
结构sock
和tcp_sock
的内容有很大不同。这种映射究竟是如何发生的?具有相同名称和类型的结构成员是否相互映射
编辑1:更具体地说,在函数tcp\u v4\u 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\u connect
中
struct tcp_sock *tp = tcp_sk(sk);
tcp_init_nondata_skb(buff, tp->write_seq++, TCPHDR_SYN);
变量write_seq
仅存在于struct tcp_sock
中,因此,当只有struct sock*sk
被传递到函数tcp_connect
时,如何将其值传递到函数
谢谢。由于构造只是一个强制转换,因此没有“映射”任何内容,sk
指向的内存位置没有实际更改任何内容
这仅在结构相似或至少以相同偏移量的相同字段开始时有效
在linux内核代码中,您可以看到struct sock
和struct tcp_sock
具有struct sock
的所有字段(tcp_sock
包含inet\u连接\u sock
,其中包含inet\u sock
,然后分别包含sock
作为第一个元素)。所以,“结构的内容……非常不同”,这是不完全正确的。它们实际上是相同的(至少对于struct sock
的大小是相同的)
为了能够正确地执行此操作,系统以某种方式“必须知道”它可以安全地将struct sock
强制转换为struct tcp_sock
——此信息通常隐藏在公共标头的某个位置,在这种情况下,隐藏在struct sock
部分中(我最近没有查过,但我想这里的信息在sk_family
)
编辑后:
实际上传递给函数的是一个指向内存区域的指针。以前发生的任何事情都不会被cast更改(如我上面所说)。如果我们可以安全地假设,sk
在某段时间之前是指向struct tcp_sock
的指针,我们可以安全地将其转换回这样的野兽。这通常是在代码中完成的,该代码在具有泛型和特定部分的数据周围移动(如本例中)。所有套接字(tcp、UDP、泛型、Unix套接字等)数据具有在所有特定套接字结构开头的struct sock
中收集的公共数据。因此,对于传入的套接字数据,该结构的所有通用部分首先由处理struct sock
的函数处理,之后的函数必须有一些大型的开关…case
,用于查看指定的ic部件,然后传递特定的指针类型
这允许采用分层的编程方法,首先将所有内容转换为通用的struct sock
,然后由所有套接字类型的通用函数处理通用部分,然后将指针转换回原来的状态,并由专业函数处理特定部分。一直以来,内存基本上用作struct sock
上的“背包”以保存特定数据的区域保持不变。具有相同名称和类型的结构成员是否相互映射
没有
tcp_sk
指针现在只指向&sk
指向的内存。现在通过访问tcp_sk
字段,您将访问分配给该指针的内存,但为了获得预期结果,存储在两个地址的数据都应有效
现在,struct sock
(套接字的网络层表示)将struct sock\u 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;
90 struct inet_connection_sock {
91 /* inet_sock has to be the first member! */
92 struct inet_sock icsk_inet;
而struct-tcp\u-sock
将struct-inet\u-connection\u-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
:
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;
90 struct inet_connection_sock {
91 /* inet_sock has to be the first member! */
92 struct inet_sock icsk_inet;
猜猜哪个struct是inet\u 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\u conn.icsk_inet.sk
您正在访问我们的sock
结构。谢谢,这消除了我的一些无知。我刚刚编辑了这个问题来添加一些具体的细节,您能看一下吗?谢谢!我编辑了这个问题以获得更精确的怀疑。您也能看一下吗?sk就像我处理的一样在这段代码中,通过访问tp->write_seq,您正在通过write_seq成员位置访问sk offset地址处的内存,并且必须确保可以访问内存,因为序列号对于TCP来说是一个至关重要的变量,如何确保在多个函数调用期间保持不变(例如,从TCP connect转到TCP send)?我在代码中找不到任何关于保留内存的内容。通过仔细检查struct sock代表的网络连接类型,可以确定这一点。好的。我正在尝试对我的协议执行类似的操作。你能告诉我在代码中的何处确保分配给struct tcp_sock的内存没有被违反?或者我可以执行以下操作吗为我的协议创建一个类似的结构,并期望它像tcp\U sock一样工作?