Порядок следования байтов
Порядок следования байтов ( byte ordering ) — это порядок, согласно которому байты расположены в машинном слове. Для разных процессоров может использоваться один из двух типов нумерации байтов в машинном слове: наименее значимый (самый младший) байт является либо самым первым (самым левым, left-most), либо самым последним (самым правым, right-most) в слове. Порядок байтов называется обратным ( big-endian ), если наиболее значимый (самый старший) байт хранится первым, а за ним идут байты в порядке убывания значимости. Порядок байтов называется прямым ( little-endian ), если наименее значимый (самый младший) байт хранится первым, а за ним следуют байты в порядке возрастания значимости.
Даже не пытайтесь основываться на каких-либо предположениях о порядке следования байтов при написании кода ядра (конечно, если код не предназначен для какой-либо конкретной аппаратной платформы). Операционная система Linux поддерживает аппаратные платформы с обоими порядками байтов, включая и те машины, на которых используемый порядок байтов можно сконфигурировать на этапе загрузки системы, а общий код должен быть совместим с любым порядком байтов.
На рис. 19.1 показан пример обратного порядка следования байтов, а на рис. 19.2 — прямого порядка следования байтов.
Рис. 19.1. Обратный (big-endian) порядок следования байтов
Рис. 19.2. Прямей (little-endian) порядок следования байтов
Аппаратная платформа i386 использует прямой (little-endian) порядок байтов. Большинство других аппаратных платформ обычно использует обратный (big-endian) порядок.
Рассмотрим, что эти типы кодирования обозначают на практике и как выглядит двоичное представление числа 1027, которое хранится в виде четырехбайтового целочисленного типа данных.
00000000 00000000 00000100 00000011
Внутренние представления этого числа в памяти при использовании прямого и обратного порядка байтов отличаются, как это показано в табл. 19.3.
Таблица 19.3. Расположение данных в памяти для разных порядков следования байтов
Адрес |
Обратный порядок |
Прямой порядок |
0 |
00000000 |
00000011 |
1 |
00000000 |
00000100 |
2 |
00000100 |
00000000 |
3 |
00000011 |
00000000 |
Обратите внимание на то, что для аппаратной платформы с обратным порядком байтов самый старший байт записывается в самый минимальный адрес памяти.
И наконец, еще один пример — фрагмент кода, который позволяет определить порядок байтов для той аппаратной платформы, на которой он выполняется.
int x = 1;
if (*(char*)&x == 1)
/* прямой порядок */
else
/* обратный порядок */
Этот пример работает как в ядре, так и в пространстве пользователя.
История терминов big-endian и little-endian
Термины big-endian и little-endian заимствованы из сатирического романа Джонатана Свифта "Путешествие Гулливера", который был издан в 1726 году. В этом романс наиболее важной политической проблемой народа лилипутов была проблема, с какого конца следует разбивать яйцо: с тупого (big) или острого (little). Тех, кто предпочитал тупой конец называли "тупоконечниками" (big-endian), тех же, кто предпочитал острый конец, называли "остроконечниками" (little-endian).
Аналогия между дебатами лилипутов и спорами о том, какой порядок байтов лучше, говорит о том, что это вопрос больше политический, чем технический.
Для каждой аппаратной платформы, которая поддерживается ядром Linux, в файле определена одна из двух констант __BIG_ENDIAN
или __LITTLE_ENDIAN
, в соответствии с используемым порядком байтов.
В этот заголовочный файл также включаются макросы из каталога include/linux/byteorder/
, которые помогают конвертировать один порядок байтов в другой. Ниже показаны наиболее часто используемые макросы.
u32 __cpu_to_be32(u32); /* преобразовать порядок байтов текущего
процессора в порядок big-endian */
u32 __cpu_to_le32(u32); /* преобразовать порядок байтов текущего
процессора в порядок little-endian */
u32 __be32_to_cpu(u32); /* преобразовать порядок байтов big-endian в
порядок байтов текущего процессора */
u32 __lе32_to_cpu(u32); /* преобразовать порядок байтов little-endian
в порядок байтов текущего процессора */
Читать дальше