Порядок проходження байтів

(byte ordering)- це порядок, згідно з яким байти розташовані в машинному слові. Для різних процесорів може використовуватися один з двох типів нумерації байтів у машинному слові: найменш значущий (наймолодший) байт є або найпершим (найлівішим, left-most), або найостаннішим (найправішим, right-most) у слові. Порядок байтів називаєтьсязворотним (big-endian),якщо найбільш значущий (найстарший) байт зберігається першим, а за ним йдуть байти в порядку зменшення значимості. Порядок байтів називаєтьсяпрямим (little-endian),якщо найменш значимий (наймолодший) байт зберігається першим, а за ним слідують байти в порядку зростання значимості.

Навіть не намагайтеся ґрунтуватися на будь-яких припущеннях про порядок байтів при написанні коду ядра (звичайно, якщо код не призначений для будь-якої конкретної апаратної платформи). Операційна система Linux підтримує апаратні платформи з обома порядками байтів, включаючи і ті машини, на яких використовуваний порядок байтів можна налаштувати на етапі завантаження системи, а загальний код має бути сумісним з будь-яким порядком байтів.

На рис. 19.1 показаний приклад зворотного порядку проходження байтів, а на рис. 19.2 - Прямого порядку проходження байтів.

Апаратна платформа i386 використовує прямий (little-endian) порядок байтів. Більшість інших апаратних платформ зазвичай використовують зворотний (big-endian) порядок.

Мал. 19.1.Зворотний (big-endian) порядок прямування байтів

Мал.19.2. Прямий(little-endian) порядок проходження байтів

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

00000000 00000000 00000100 00000011

Внутрішні уявлення цього числа у пам'яті при використанні прямого та зворотного порядку байтів відрізняються, як показано в табл. 19.3.

Таблиця 19.3.Розташування даних у пам'яті для різних порядків проходження байтів

І нарешті, ще один приклад — фрагмент коду, який дозволяє визначити порядок байтів для апаратної платформи, на якій він виконується.

Цей приклад працює як у ядрі, так і в просторі користувача.

Історія термінів big-endian та little-endian

Терміни big-endian і little-endian запозичені з сатиричного роману Джонатана Свіфта "Подорож Гулівера", який був виданий в 1726 році. У цьому романі найважливішою політичною проблемою народу ліліпутів була проблема, з якого кінця слід розбивати яйце: з тупого (big) або гострого (little). Тих, хто вважав за краще тупий кінець називали "тупоконечниками" (big-endian), тих же, хто вважав за краще гострий кінець, називали "гостроконечниками" (little-endian).

Аналогія між дебатами ліліпутів і суперечками про те, який порядок байтів кращий, говорить про те, що це питання є більш політичним, ніж технічним.

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

Для кожної апаратної платформи, яка підтримується ядром Linux, у файлі визначено одну з двох констант BIG_ENDIAN або

LITTLE_ENDIAN, відповідно до порядку байтів, що використовується.

Цей заголовковий файл також включають макроси з каталогу include / linux/byteorder/ , які допомагають конвертувати один порядок байтів в інший. Нижче показані найчастіше використовувані макроси.

u23 cpu_to_be32(u32); /* перетворити порядок байтів поточного процесора на порядок big-endian */

u32 cpu_to_le32(u32); /* перетворитипорядок байтів поточного процесора до порядку little-endian */

u32 be32_to_cpu(u32); /* перетворити порядок байтів big-endian на

порядок байтів поточного процесора */

u32 lе32_to_cpus(u32); /* перетворити порядок байтів little-endian на порядок байтів поточного процесора */

Ці макроси виконують перетворення одного порядку байтів на інший. У разі коли порядки байтів, між якими виконується перетворення, однакові (наприклад, якщо виконується перетворення у зворотний порядок байтів і процесор теж використовує такий самий порядок), то ці макроси не роблять нічого. В іншому випадку повертається перетворене значення.

Ніколи не можна прив'язуватися до будь-якої конкретної частоти генерації переривання системного таймера і, відповідно, скільки разів на секунду змінюється змінна jiffies . Завжди потрібно використовувати константу HZ, щоб правильно визначати інтервали часу. Це дуже важливо, тому що значення частоти системного таймера може відрізнятися не тільки для різних апаратних платформ, але і для апаратної платформи при використанні різних версій ядра.

Наприклад, константа HZ для апаратної платформи х86 зараз дорівнює 1000. Це означає, що переривання таймера виникає 1000 разів на секунду, або кожну мілісекунду. Однак до серії ядер 2.6 для апаратної платформи х86 значення константи HZ дорівнювало 100. Для різних апаратних платформ ці значення відрізняються: для апаратної платформи alpha константа HZ дорівнює 1024, а для платформи ARM - 100.

Ніколи не можна порівнювати значення змінної jiffie s із числом, таким як

1000, і думати, що це завжди означатиме те саме. Для отримання інтервалів часу необхідно завжди множити чи ділити на константу HZ, як унаступний приклад.

HZ /* одна секунда */ (2*HZ) /* дві секунди */ (HZ/2) /* півсекунди */ (HZ/100) /* 10 мс */ (2*Н2/100) /* 20 мс */

Джерело: Лав, Роберт. Розробка ядра Linux, 2-ге видання. : Пров. з англ. - М.: ТОВ «І.Д. Вільямі» 2006. - 448 с. : іл. - Парал. тит. англ.