es4*_*483 2 c attributes gcc struct packed
我正在尝试构建一个简单的自定义应用程序层协议,本质上是携带时间戳以及一些其他有用的信息,以便在不同的 Linux 系统之间执行少量网络测量。
在我最初的想法中,就 Linux 系统而言,该实现应该在不同平台(x86、ARM 等)之间尽可能可移植。
为了管理标头,我创建了以下结构:
struct myhdr {
__u8 reserved; // 1 byte
__u8 ctrl; // 1 byte
__u16 id; // 2 bytes
__u16 seq; // 2 bytes
__u16 len; // 2 bytes
struct timeval sendtime; // 8 or 16 bytes
};
Run Code Online (Sandbox Code Playgroud)
之后,一些有效负载数据可能存在也可能不存在(如果 len=0)。由于这些数据必须通过网络发送,如果我没记错的话,我需要打包结构,而不需要任何对齐填充。
我的疑问实际上是这是否可以被认为是已经打包的,主要是因为struct timeval, 的存在来携带时间戳。
32位系统下,struct timeval应该是8字节。在64位系统下,它应该是16字节(刚刚通过打印测试过sizeof(struct timeval))。
在 32 位系统下,由于 1+1+2+2+2 字节 = 8 字节(即 的大小),可以安全地假设它已经打包了sendtime?或者在任何情况下都会添加填充,以便将每个字段与最后一个字段(最大的字段)对齐?
那么在最后一个字段为 16 字节的 64 位系统中会发生什么?我认为无论如何,该结构将不再“按布局打包”(这是正确的吗?)。
添加__attribute__((packed))足够的且始终必要的内容来确保在针对不同平台编译代码时结构被打包?有更好的解决方案吗?
如果您定义了有线协议,则确实需要使用您自己的类型。为了安全起见,您应该使用 64 位来表示 1970 年以来的秒数,即使许多 32 位系统仍然使用 32 位计数器。
struct timeval来自系统标头,基本上可以具有任何大小,从 8 字节开始。我确信有 32 位系统的大小为 12(64 位time_t用于tv_sec避免 Y2038 问题,32 位long/suseconds_t用于tv_usec)。此外,POSIX 仅要求struct timeval具有某些成员。某些系统在其系统标头中具有显式字段,以避免编译器隐式填充,从而导致(假设的)打包行为进一步差异。
虽然__attribute__ ((pack))不递归应用(因此sizeof (p->sendtime)将 equal )sizeof (struct timeval),但它仍然会将整个结构(包括成员sendtime)的对齐方式减少到 1,因此该成员可能会未对齐并且不适合直接与需要 a 的函数一起使用struct timeval *。
| 归档时间: |
|
| 查看次数: |
1386 次 |
| 最近记录: |