我在调试下面的代码片段来分析结构成员的字节对齐。使用属性对齐时的内存对齐(1)
#include <stdio.h>
#include <stdint.h>
#include <string.h>
struct v_hdr {
uint16_t vlan_tci;
uint16_t eth_proto;
}__attribute__((aligned(1)));
struct esp_hdr {
uint32_t fpa_esp_spi;
uint32_t fpa_esp_sequenceid;
}__attribute__((aligned(1)));
struct f_cookie {
uint16_t vlan_ports;
uint16_t untagged_vlan_ports;
struct v_hdr vlan_hdr;
uint16_t tcp_flags;
uint32_t *eth_hdr;
uint32_t *ipv4_hdr;
struct esp_hdr esp;
}__attribute__((aligned(1)));
struct metadata {
struct f_cookie flow_cookie;
} __attribute__((aligned(1)));
int main()
{
struct metadata meta;
memset (&meta, 0, sizeof(struct metadata));
/* 16 */ meta.flow_cookie.vlan_ports = 0xffff;
/* 16 */ meta.flow_cookie.untagged_vlan_ports = 0xffff;
/* 16 */ meta.flow_cookie.vlan_hdr.vlan_tci = 0xffff;
/* 16 */ meta.flow_cookie.vlan_hdr.eth_proto = 0xffff;
/* 16 */ meta.flow_cookie.tcp_flags = 0xffff;
/* 32 */ meta.flow_cookie.eth_hdr = 0xffffffff;
/* 32 */ meta.flow_cookie.ipv4_hdr = 0xffffffff;
/* 32 */ meta.flow_cookie.esp.fpa_esp_spi = 0xffffffff;
/* 32 */ meta.flow_cookie.esp.fpa_esp_sequenceid = 0xffffffff;
return 0;
}
这里是gdb的X转储return语句之前 -
(gdb) p sizeof meta
$2 = 40
(gdb) x/40bt &meta
0x7fffffffe2d0: 11111111 11111111 11111111 11111111 11111111 11111111 11111111 11111111
0x7fffffffe2d8: 11111111 11111111 00000000 00000000 00000000 00000000 00000000 00000000
0x7fffffffe2e0: 11111111 11111111 11111111 11111111 00000000 00000000 00000000 00000000
0x7fffffffe2e8: 11111111 11111111 11111111 11111111 00000000 00000000 00000000 00000000
0x7fffffffe2f0: 11111111 11111111 11111111 11111111 11111111 11111111 11111111 11111111
我的问题是,为什么meta.flow_cookie.eth_hdr
不tcp_flags
后,在4字节边界放在哪里?即在(0x7fffffffe2d8 + 4)
。而meta.flow_cookie.ipv4_hdr
不在0x7fffffffe2e0
?
尽管应用aligned(1)
属性,为什么这两个成员都放置在8字节边界? PS。我不想使用属性packed
。我只想让成员尽可能与4字节地址对齐。它可以实现吗?
GCC文档明确指出:*对齐的属性只能增加对齐;但你也可以通过指定包装来减少它。*为什么你看到不相信的理由?如果你想完成什么'包装',你为什么不想使用'packed'? – tofro
@tofro:如果是这样的话,为什么'fpa_esp_sequenceid'从4字节地址开始?实际上'元数据'结构在开始时包含几个其他的位域变量。使用打包导致这些变量的未对齐内存访问,导致性能滞后。 – tcpip
如果**不指定'aligned(1)',那么'fpa_esp_sequenceid'对齐如何?我非常怀疑'对齐(1)'does * anything * – tofro