使用属性对齐时的内存对齐(1)
Memory alignment while using attribute aligned(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;
}
这是 return 语句之前的 gdb x 转储 -
(gdb) p sizeof meta
= 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 字节地址。可以实现吗?
引用您的代码摘录:
/* 16 */ meta.flow_cookie.tcp_flags = 0xffff;
/* 32 */ meta.flow_cookie.eth_hdr = 0xffffffff;
/* 32 */ meta.flow_cookie.ipv4_hdr = 0xffffffff;
您假设 meta.flow_cookie.eth_hdr
和 meta.flow_cookie.ipv4_hdr
指针 是 32 位长并且您的系统基于您的 gdb
转储,好像不是32位架构。
请记住 sizeof(uint32_t *)
与 sizeof(uint32_t)
不同。如果由于某种原因这些值相同(在 32 位架构的情况下),那纯属巧合。
指针的大小始终足以容纳属于底层架构完整地址 space 的任何地址。例如,sizeof(uint32_t *)
在 64 位架构上至少有 8 个字节长(64 位长)。
由于您的架构似乎有一个 64 位地址 space,您对对齐所做的假设是有缺陷的。
我正在调试以下代码片段以分析结构成员的字节对齐。
#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;
}
这是 return 语句之前的 gdb x 转储 -
(gdb) p sizeof meta
= 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 字节地址。可以实现吗?
引用您的代码摘录:
/* 16 */ meta.flow_cookie.tcp_flags = 0xffff; /* 32 */ meta.flow_cookie.eth_hdr = 0xffffffff; /* 32 */ meta.flow_cookie.ipv4_hdr = 0xffffffff;
您假设 meta.flow_cookie.eth_hdr
和 meta.flow_cookie.ipv4_hdr
指针 是 32 位长并且您的系统基于您的 gdb
转储,好像不是32位架构。
请记住 sizeof(uint32_t *)
与 sizeof(uint32_t)
不同。如果由于某种原因这些值相同(在 32 位架构的情况下),那纯属巧合。
指针的大小始终足以容纳属于底层架构完整地址 space 的任何地址。例如,sizeof(uint32_t *)
在 64 位架构上至少有 8 个字节长(64 位长)。
由于您的架构似乎有一个 64 位地址 space,您对对齐所做的假设是有缺陷的。