Ошибка Solaris Bus после копирования выровненных данных в новое местоположение не происходит

Итак, короткая история: моя программа получает буфер необработанных байтов (u_char), который представляет сетевой пакет. Я пытаюсь проанализировать информацию в этом пакете, и я делаю это, используя определенные системой структуры заголовков (ether_header, ip, ip6, tcphdr, udphdr). Я реализовал это как в Linux, так и в AIX, и это сработало, но по какой-то причине я получаю ошибку шины, когда делаю это в Solaris.

То, как я получаю данные, - это просто приведение каждой части буфера к одной из структур и чтение данных. Например, если у меня есть

u_char buffer[] = {...some bytes...};
struct ether_header *ethdr = (struct ether_header *)buffer;
struct ip *iphdr = (struct ip *) (buffer + sizeof(struct ether_header));
etc. etc.

Затем я могу получить информацию, которая мне нужна:

iphdr->ip_v; //to get the version
etc->etc; //to get whatever piece of data I need

Обычно в Linux и AIX это работает нормально (некоторые структуры имеют разные имена в разных системах, но это не главное), но при попытке запустить это в Solaris я получаю сообщение об ошибке шины, когда оно доходит до iphdr->ip_v; после struct ip *iphdr = (struct ip *) (buffer + sizeof(struct ether_header));, После некоторого расследования я обнаружил, что это вызвано попыткой доступа к невыровненной памяти. Это имеет смысл, поскольку размер заголовка Ethernet составляет всего 14 байтов, поэтому заголовок IP не выровнен в байтах в массиве.

Я попытался обойти это, скопировав соответствующие фрагменты в отдельный буфер, прежде чем пытаться его прочитать.

memcpy(&buffer_copy, buffer + sizeof(struct ether_header), sizeof(struct ip));
struct ip *iphdr = &buffer_copy;
iphdr->ip_v;
etc.

Это работает, но я не понимаю почему. Почему memcpy не выдает ошибку шины, когда пытается получить доступ к той же области памяти? Мне не нравится решение, которое я придумала, и пытаюсь лучше понять ситуацию, чтобы придумать что-то еще. Может быть, мне не хватает части головоломки?

1 ответ

На оборудовании SPARC у вас есть два варианта:

  1. Не пишите код, который обращается к памяти способом, который вызывает ошибку шины.
  2. Скомпилируйте с помощью компиляторов Solaris Studio и используйте -xmemalign=1iопция командной строки. Это приведет к тому, что двоичный файл будет работать медленнее двоичного, который предполагает правильно выровненный доступ к памяти.

Также посмотрите этот вопрос.

Другие вопросы по тегам