Я пытаюсь создать простой пользовательский протокол прикладного уровня, содержащий метку времени и некоторую другую полезную информацию, чтобы выполнить несколько измерений сети между различными системами Linux.
Реализация, в моей первоначальной идее, должна быть максимально переносимой между различными платформами (x86, ARM, ...), насколько это касается систем Linux.
Для управления заголовком я создал следующую структуру:
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
};
После чего некоторые полезные данные могут присутствовать или не присутствовать (если len = 0).
Поскольку эти данные должны быть отправлены по сети, мне нужна, если я не ошибаюсь, структура, которая должна быть упакована, без каких-либо выравниваний.
Я сомневаюсь, действительно ли это можно считать уже упакованным или нет, в основном из-за наличия struct timeval
для переноса метки времени.
В 32-битных системах struct timeval
должно быть 8 байтов. В 64-битных системах это должно быть 16 байтов (просто протестируйте это, напечатав sizeof(struct timeval)
).
Безопасно ли в 32-битных системах предполагать, что он уже упакован, из-за того, что 1 + 1 + 2 + 2 + 2 байта = 8 байтов, что составляет размер sendtime
? Или в любом случае будет добавлен отступ, чтобы выровнять каждое поле по последнему, которое является самым большим?
Что происходит тогда в 64-битных системах, где последнее поле составляет 16 байтов? Я думаю, что в любом случае структура больше не будет «упакована по макету» (это правильно?).
Является ли добавление __attribute__((packed))
достаточным и всегда необходимым для обеспечения того, чтобы структура была упакована при компиляции кода для разных платформ? Есть ли лучшие решения?