C 接收到的网络数据包中的内存对齐问题

C 接收到的网络数据包中的内存对齐问题,c,memory,linux-kernel,network-programming,C,Memory,Linux Kernel,Network Programming,我正在linux内核中编写一个自定义协议。我使用以下结构 struct syn { __be32 id; __be64 cookie; }; struct ack { __be32 id; // Right now, setting it to 14 (Just a random choice) __be32 sequence; }; struct hdr { ............ __be32 type; //l

我正在linux内核中编写一个自定义协议。我使用以下结构

struct syn {
    __be32 id;      
    __be64 cookie;
};

struct ack {
    __be32 id;      // Right now, setting it to 14 (Just a random choice)
    __be32 sequence;
};

struct hdr {
    ............
    __be32 type;   //last element
};
当我发送和接收数据包时,我将结构
syn
ack
(对于不同的数据包)映射到hdr->type的地址

理想情况下,这意味着id(在syn和ack结构中)应该映射到
hdr->type
,而
struct hdr
之后的任何内容都应该映射到
syn->cookie
ack->sequence
,这取决于我映射到
hdr->type
的结构

但是在打印出这些变量的内存地址时,我得到了以下结果

//For struct syn
hdr->type at ffff880059f55444
syn->id at ffff880059f55444
syn->cookie at ffff880059f5544c  //See the last two bits

//For struct ack_frame
hdr->type at ffff880059f55044
ack->id at ffff880059f55044
ack->sequence at ffff880059f55048  //See the last two bits
那么为什么
syn->cookie
ack->sequence
相对于
hdr->type
的偏移量不同,而
ack->id
syn->id
的大小相同呢

编辑1:我使用

char *ptr = (char *)&hdr->type;
//For syn
struct syn *syn1 = (struct syn *)ptr
//For ack
struct ack *ack1 = (struct ack *)ptr

由于您使用64位工作,编译器将填充结构如下:

struct syn {
    uint32_t id
    uint32_t hole -- the compiler must add here cause it mist align
    uint64_t seq
}

我想数据没有漏洞,所以要修复它,您需要将seq设置为uint32_t,稍后再对其进行强制转换。

由于您使用64位,编译器将填充结构如下:

struct syn {
    uint32_t id
    uint32_t hole -- the compiler must add here cause it mist align
    uint64_t seq
}
我想数据没有漏洞,所以要修复它,您需要将seq设置为uint32\u t,稍后再进行转换。

查看打包的
。无论出于何种原因,GCC不允许我直接链接到该部分。


查看打包的
。无论出于何种原因,GCC不允许我直接链接到该部分。

您应该按照以下方式定义您的结构。属性压缩意味着allignment应为1字节。 以下结构的长度为12字节。如果您不使用“attribyte”关键字,您的结构将是16字节长

struct yours{
 __be32 id;      
 __be64 cookie;
}__attribute__((__packed__));

您应该按照以下方式定义您的结构。属性压缩意味着allignment应为1字节。 以下结构的长度为12字节。如果您不使用“attribyte”关键字,您的结构将是16字节长

struct yours{
 __be32 id;      
 __be64 cookie;
}__attribute__((__packed__));

这里的关键词是对齐…你所说的“我将结构syn和ack(针对不同的数据包)映射到hdr->type的地址”是什么意思?我闻到访问左值类型不是对象有效类型的对象和/或访问超出范围的对象的未定义行为。是的,我理解这一点,但我需要一种方法确保每次都可以以相同的方式访问数据包,即使我使用不同的结构填充数据包。你为什么这样做?你为什么不写一些你真正想做的代码,而不是用魔法来实现它呢?我正在写一些我想做的代码。我试着理解我写的代码的行为,并不是真的期望这里有魔力。这里的关键词是对齐…你所说的“我将结构syn和ack(针对不同的数据包)映射到hdr->type的地址”是什么意思?我闻到访问左值类型不是对象有效类型的对象和/或访问超出范围的对象的未定义行为。是的,我理解这一点,但我需要一种方法确保每次都可以以相同的方式访问数据包,即使我使用不同的结构填充数据包。你为什么这样做?你为什么不写一些你真正想做的代码,而不是用魔法来实现它呢?我正在写一些我想做的代码。我试图理解我写的代码的行为,并不是真的期望这里有魔力。这是有道理的。我将尝试并报告:)然而,我相信这将使内存访问变慢是有意义的。我将尝试并报告:)然而,我相信这会使内存访问速度变慢,包会压缩内存,但它会改变结构的顺序。所以指针不合适。pack会压缩它,但会改变结构的顺序。所以指针不合适。