что такое big endian и little endian

Что такое big endian и little endian

Чтобы было понятнее, рассмотрим пример. 4-байтное целое число 0x01020304 будет сохранено в памяти системы big endian следующим образом:

Байт0Байт1Байт2Байт3
0x010x020x030x04

Big endian всегда используется для так называемого сетевого порядка байт (network byte order), который применяется при кодировании адресов в сетевых протоколах.

Та же самая величина, которая будет храниться в памяти системы little endian, разместится в противоположном порядке:

Байт0Байт1Байт2Байт3
0x040x030x020x01

Linux kernel может быть либо big endian, либо little endian, в зависимости от архитектуры, в расчете на которую kernel скомпилировано. Ниже в таблице показан endianness для различных типов архитектур процессоров и протоколов.

Big EndianLittle EndianОба варианта
Архитектуры процессоров
AVR32
FR-V
H8300
PA-RISC
S390
Motorola 680×0 PowerPC
SPARC
Alpha
CRIS
Blackfin
Intel 64
IA-32 (x86) MN10300
AT91SAM7
Cortex, STM32
ARM
SuperH (sh)
M32R
MIPS
Xtensa

Протоколы
TCP/IPUSB

Примечание: процессор ARM может быть либо с архитектурой big endian, либо little endian, в зависимости от типа применяемого чипа, однако чаще всего это big endian. Архитектура PowerPC может быть сконфигурирована для работы либо в режиме big endian, либо little endian, но в Linux используется только big endian.

[Почему следует беспокоиться об endianness]

Как уже упоминалось, порядок байт на низком уровне в системе полностью прозрачен для программиста (про endianness можно часто забыть). Однако могут быть проблемы, когда происходит обмен данными с другой системой, поскольку эта другая система может ожидать появления данных в блоке памяти в противоположном порядке.

Например, если заранее нельзя предсказать тип системы на каком-то дальнем окончании сетевого соединения, сетевые протоколы должны заранее определить порядок байт, используемый для хранения многобайтных величин в заголовках пакетов. В этом случае порядок байт называют сетевым порядком байт (network byte order), и для протокола TCP/IP это будет big endian. Таким образом, отправляющая пакеты система конвертирует данные из локального порядка хранения байт в сетевой. После этого принимающая система преобразует данные из сетевого порядка байт в локальный. На практике, когда есть жесткие требования к быстродействию и заранее известно, что локальный порядок байт такой же, как сетевой, операция конверсии отбрасывается в целях оптимизации.

[Как программно определить endianness]

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

Строки 1..4 определяют переменную foo, к которой можно обращаться либо как к числу типа int (тип int почти всегда состоит из нескольких байт) или как к массиву символов characters. На строке 6 переменная инициализируется целым значением 1, так что как минимум один байт в многобайтном числе станет равен 1 (наименее значащий байт), а все остальные значащие байты будут нулями. Если байт 0 массива наименее значимый, то он станет равным 1, и это означает, что система little endian. Если байт 0 массива самый значимый байт, то он будет нулем, и значит система big endian.

Kernel определяет различные типы переменных и макросы для обработки значений, которые зависят от порядка байт, отличающегося от используемого процессором текущей системы.

[Идентификаторы типов]

Следующие идентификаторы соответствуют типам u16, u32 и u64, за исключением случаев, когда они определены с поразрядным (bitwise) атрибутом, который вводят для ограничения применения их как целых чисел. Bitwise-атрибут используется утилитой sparse, чтобы гарантировать, что переменная преобразована в локальный тип процессора перед тем, как над переменной выполнятся другие (небезопасные, unsafe) операции.

Следующие типы можно применять для endian-зависимых переменных, после подключения header-файла linux/kernel.h.

[Макросы для преобразований]

Имеется множество макросов для преобразования порядка байт, используемого текущим процессором, в порядок либо big, либо little endian. Дополнительно для каждого типа конверсии имеются отдельные макросы для 16-, 32- и 64-разрядных значений. Имена макросов кодируют исходный и целевой порядок байт значения, так что по имени сразу понятно, что каждый макрос делает.

В целях написания портируемого кода Вы должны всегда применять эти макросы для преобразования из одного целевого порядка байт в другой, даже если заранее знаете, что это не требуется для того процессора, который сейчас используете. Если исходный и целевой порядок байт одинаковый, то макрос не будет выполнять никаких действий, так что применение макросов на быстродействии никак не скажется.

Следующие макросы вернут значение после конвертации. Обратите внимание, что заголовочный файл linux/kernel.h является заголовком, который должен быть подключен к файлам исходного кода, где макросы используются, но это не тот файл заголовка, где макросы реально определены.

Следующие макросы делают то же самое, что и предыдущие, но здесь место расположения исходной величины и преобразованной величины совпадают. Обратите внимание, что имена этих макросов такие же, только добавлен суффикс «s» (от латинской фразы in situ, что обозначает в том же месте) в конце каждого имени.

Следующие макросы предоставляют алиасы для имен функций, которые обычно применяются для преобразования порядка байт в коде сетевых приложений. Первые два макроса используются для преобразования из локального в сетевой порядок байт. Остальные два предоставляют обратное преобразование. Буквы «s» и «l» в конце имен в этом случае означают short (16-битное значение) и long (32-битное значение).

Как отмечалось ранее, сетевой порядок байт всегда big endian, и реализация этих макросов гарантирует корректное использование порядка байт сетевым хостом.

Источник

Начинающим: что такое Big-Endian и Little-Endian

Знаю, что для начинающих разработчиков часто такая простая, вроде бы, вещь, как «порядок байтов» становится просто наказанием.

И даже знаю, почему. Пока мы работаем с байтами все вполне однозначно, но стоит перейти к словам, либо двойным словам, могут начаться «странности». Вроде бы нужно передать слово 0x1234. В эмуляторе разработчик видит 0x1234, переменную в отладчике ему показывают 0x1234 и все хорошо. Включаем прямой доступ к памяти, запускаем передачу. и принимаем на другом конце 0x3412.

И в институте, вроде, учили про Big-Endian и Little-Endian, да кто же вспоминает, чему там учили.

Всегда надо учитывать порядок данных при передаче от одного процессора к другому, иначе они банально могут друг-друга не понять, либо понять неверно.

Порядок от старшего к младшему (Big-endian)

Это привычный нам порядок записи. Слово 0x1234 будет храниться в памяти как два последовательных байта 0x12 0x34.

Длинное слово 0x12345678 будет лежать в памяти следующим образом: 0x12 0x34 0x56 0x78.

Big Endian

76543210
00010010
00110100
01010110
01111000

Такой порядок байт используется в TCP/IP, процессорах SPARC и 68k.

Порядок от младшего к старшему (Little-Endian)

При хранении данных в памяти в Little-Endian слово 0x1234 расположится в памяти так: 0x34 0x12.

Little Endian

76543210
00110100
00100011

Обратите внимание, что порядок бит в байте не меняется, так же как и порядок ниблов!!

Длинное слово 0x12345678 будет лежать в памяти следующим образом: 0x78 0x56 0x34 0x12.

Little Endian

76543210
01111000
01010110
01000011
00100001

То есть самый старший байт лежит по последнему байтовому адресу. Это необходимо учитывать, если Вы пытаетесь получить данные через указатели разных типов.

Например, банальный код

Little-Endian характерен для USB, PCI, а также процессоров x86 и VAX.

Смешанный порядок (Middle-Endian)

Сами слова в пределах длинного слова могут лежать от старшего к младшему, однако в пределах слова используется порядок от младшего к старшему.

Двухбайтовое слово хранится аналогично Big Endian.

То есть длинное слово 0x12345678 будет представлено в памяти как гибрид Big Endian и Little Endian 0x34 0x12 0x78 0x56.

Middle Endian

76543210
00110100
00010010
01111000
01010110

Такой порядок использовался в PDP-11, есть ли на данный момент процессоры, использующие этот порядок расположения байт, мне не известно.

Некоторые процессоры (ARM, PowerPC) умеют работать с разным порядком байт, и его можно задать при конфигурировании процессора.

Как писать хорошо переносимый код?

Естественный вопрос: как писать такой код, который не придется переписывать под каждую конкретную архитектуру процессора? Может ли программа сама определять порядок байт?

Да, может! И все давно придумано до нас. Приведу несколько примеров от IBM.

Источник

Сокеты Windows. Порядок байтов

в этой статье и двух сопутствующих статьях объясняются некоторые проблемы, связанные с программированием сокетов Windows. В этой статье описывается порядок байтов. другие проблемы описаны в статьях: сокеты Windows: блокировка и Windowsные сокеты: преобразование строк.

Если вы используете или наследуете от класса CAsyncSocket, вам придется самостоятельно управлять этими проблемами. Если вы используете или наследуете от класса CSocket, MFC управляет ими.

Порядок байтов

Различные архитектуры компьютеров иногда хранят данные, используя различные порядки байтов. Например, компьютеры на базе технологии Intel хранят данные в противоположном порядке компьютеров Macintosh (Motorola). Порядок байтов Intel, называемый прямым порядком байтов, также является обратным по отношению к сетевому стандарту с обратным порядковым порядком байтов. Эти термины объясняются в следующей таблице.

Упорядоченность больших и Little-Endian байт

Порядок байтовЗначение
Big-EndianНаиболее значимый байт находится в левом конце слова.
Little-EndianНаиболее значимый байт находится в правом конце слова.

Как правило, не нужно беспокоиться о преобразовании порядка байтов для данных, отправляемых и получаемых по сети, но существуют ситуации, в которых необходимо преобразовать заказы байтов.

Когда необходимо преобразовать порядок байтов

Порядок байтов необходимо преобразовать в следующих ситуациях:

Вы передаете сведения, которые должны интерпретироваться сетью, а не данные, отправляемые на другой компьютер. Например, можно передать порты и адреса, которые должны быть понятны сети.

Серверное приложение, с которым вы обмениваетесь данными, не является приложением MFC (и у вас нет исходного кода). Это вызывает преобразование порядка байтов, если два компьютера не имеют одинаковый порядок байтов.

Если не нужно преобразовывать порядок байтов

Вы можете избежать операций преобразования порядка байтов в следующих ситуациях:

Компьютеры на обоих концах могут согласиться не менять байты, и оба компьютера используют одинаковый порядок байтов.

Сервер, с которым вы обмениваетесь данными, является приложением MFC.

У вас есть исходный код для сервера, с которым вы обмениваетесь данными, поэтому вы можете явно определить, нужно ли преобразовывать побайтовые заказы.

Сервер можно перенести в MFC. Это довольно просто, и результат обычно меньше, чем быстрее.

Работая с CAsyncSocket, необходимо самостоятельно управлять любыми необходимыми преобразованиями порядка байтов. Windows Сокеты стандартизируют модель порядка байтов с обратным порядком следования и предоставляют функции для преобразования между этим заказом и другими. Однако CArchive, который используется с CSocket, использует противоположный порядок («с прямым порядком следования байтов)», но CArchive позаботится о преобразованиях порядка байтов. используя это стандартное упорядочение в приложениях или используя функции преобразования порядка байтов Windows сокетов, можно сделать код более переносимым.

Идеальным вариантом использования сокетов MFC является ситуация, когда вы пишете оба конца связи: использование MFC на обоих концах. если вы создаете приложение, которое будет взаимодействовать с приложениями, не использующими MFC, например с FTP-сервером, вам, вероятно, придется самостоятельно управлять обменом байтов перед передачей данных в архивный объект с помощью подпрограмм преобразования Windows sockets нтохс, нтохл, хтонс и хтонл. Ниже в этой статье приводятся примеры этих функций, используемых при взаимодействии с приложениями, не использующими MFC.

Если другой конец обмена данными не является приложением MFC, необходимо также избегать потоковой передачи объектов C++, производных от, CObject в архив, так как получатель не сможет их обрабатывать. см. примечание в Windows sockets: использование сокетов с архивами.

дополнительные сведения о побайтовых заказах см. в описании спецификации сокетов Windows, доступной в Windows SDK.

Пример преобразования Byte-Order

В следующем примере показана функция сериализации для CSocket объекта, который использует Архив. кроме того, в нем показано использование функций преобразования порядка байтов в API Windows sockets.

В этом примере представлен сценарий, в котором выполняется запись клиента, взаимодействующего с серверным приложением, не являющимся MFC, для которого отсутствует доступ к исходному коду. В этом сценарии необходимо предположить, что сервер, не являющийся сервером MFC, использует стандартный сетевой порядок байтов. В отличие от этого, клиентское приложение MFC использует CArchive объект с CSocket объектом и CArchive использует порядок байтов с прямым порядком следования, противоположный стандарту сети.

Предположим, что сервер, не относящийся к MFC, с которым планируется обмениваться данными, имеет установленный протокол для пакета сообщений, который выглядит следующим образом:

В терминах MFC это выражение выражается следующим образом:

В C++, по struct сути, это то же самое, что и класс. Message Структура может иметь функции элементов, например Serialize функцию члена, объявленную выше. Serialize Функция члена может выглядеть следующим образом:

В этом примере вызывается преобразование порядка байтов данных, так как существует четкое несоответствие порядка байтов серверного приложения, не относящегося к MFC, на одном конце и CArchive используемого в клиентском приложении MFC на другом конце. в примере показаны несколько функций преобразования порядка байтов, которые Windows предоставляются сокетами. Эти функции описаны в следующей таблице.

Windows Функции преобразования Byte-Order сокеты

ФункцияНазначение
нтохсПреобразование 16-разрядного количества из сетевого байтового порядка в порядок размещения байтов (с обратным порядком байтов (Big-endian).
нтохлПреобразование 32-разрядного количества из сетевого байтового порядка в порядковый номер размещения в байтах (с обратным порядком байтов).
хтонсПреобразует 16-разрядное количество из байтового порядка узла в сетевой байтовый порядок (с прямым порядком байтов с обратным порядком байтов).
хтонлПреобразование 32-разрядного количества из байтового порядка узла в сетевой байтовый порядок (с прямым порядком байтов с обратным порядком байтов).

Еще одной точкой этого примера является то, что если приложение сокета на другом конце связи является приложением, не являющимся MFC, необходимо избегать выполнения следующих действий:

Источник

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *