数据与网络编程对齐

关于数据对齐,我有点困惑。 在x86上,我们通常认为对齐是理所当然的。 但是,我正在对一个非常严格的系统进行编程,如果我尝试访问未对齐的数据,则会出错。

inheritance人我的问题:

首先,我将向您展示我的一些结构:

struct sniff_ethernet { u_char ether_dhost[6]; /* Destination host address */ u_char ether_shost[6]; /* Source host address */ u_short ether_type; /* IP? ARP? RARP? etc */ }; struct sniff_ip { u_char ip_vhl; /* version <> 2 */ u_char ip_tos; /* type of service */ u_short ip_len; /* total length */ u_short ip_id; /* identification */ u_short ip_off; /* fragment offset field */ u_char ip_ttl; /* time to live */ u_char ip_p; /* protocol */ u_short ip_sum; /* checksum */ struct in_addr ip_src,ip_dst; /* source and dest address */ }; 

我正在处理pcap。 Pcap会向我返回一个指向数据包的指针:

 u_char *packet; 

让我们假装数据包是几百字节。 我通常做的是将该数据包转换为几个struct指针,因此我可以直接访问数据。

 struct sniff_ethernet *seth = (struct sniff_ethernet *) packet; struct sniff_ip *sip = (struct sniff_ip *) (packet + 14); // 14 is the size of an ethernet header 

好。 所以一切看起来都很棒吗? 在x86上,一切似乎都正常。 在任何其他具有严格对齐的原型上,我在访问某些值时遇到问题,并且通常会产生sigbus。 例如:

 sip->ip_len = 0x32AA; 

要么

 u_short val = sip->ip_len; 

导致错误。 我猜它是因为它在演员的内存中错位了。 在进行这类演员表时,通常最好的办法是什么?

简单的方法是使用memcpy

 struct sniff_ip sip; memcpy(&sip, packet + 14, sizeof(sip)); 

这假设您的两台机器使用相同的字节顺序,并且一直小心地考虑结构填充。

处理此问题的更难和更通用的方法是从单个字节构造值:

 u_short val; int offset = 14 + offsetof(sniff_ip, ip_len); val = packet[offset] + (packet[offset+1] << 8); // assuming little endian packet 

当然,您可能会使用函数或宏来抽象它。