【问题标题】:Data Alignment with network programming数据对齐与网络编程
【发布时间】:2010-10-03 03:04:41
【问题描述】:

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

这是我的问题:

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

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 << 4 | header length >> 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 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;

导致错误。我猜是因为它在演员的记忆中没有对齐。在进行此类强制转换时,通常最好的处理方法是什么?

【问题讨论】:

  • 在 gcc 中,你有 __attribute__((packed)) 告诉编译器紧密对齐结构,没有任何填充。
  • __attribute__((packed)) 在这种情况下没有任何区别,因为这些结构没有填充。

标签: c networking alignment


【解决方案1】:

简单的方法是使用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

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

【讨论】:

  • 不使用+&lt;&lt;,你可以对一个中间变量做memcpy(),然后使用ntohs()从网络转换到主机字节序。
  • 是的,但这假设结构最初是使用网络顺序(大端)填充的。我从问题中得到的印象是它们是使用 x86 (little endian) 顺序填写的。
  • 从问题中,“pcap will return a pointer to a data packet to me”表示代码正在接收数据包;以太网类型和 IP 标头中的字段都是 big-endian,而不是 little-endian。 x86 与非 x86 的问题在于对齐要求,而不是字节顺序; x86(默认情况下)不需要对齐,但一些其他指令集架构(例如,SPARC - 默认情况下恰好是大端)确实需要它。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-02-14
  • 1970-01-01
  • 1970-01-01
  • 2023-03-29
  • 1970-01-01
  • 1970-01-01
  • 2014-06-30
相关资源
最近更新 更多