вирівнювання даних

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

водительности. При написанні переноситься коду необхідно запобігати проблемам, пов'язані з вирівнюванням, а дані всіх типів повинні мати природне вирівнювання.

Як уникнути проблем з вирівнюванням

Компілятор зазвичай запобігає проблеми, пов'язані з вирівнюванням, шляхом природного вирівнювання всіх типів даних. Насправді, розробники ядра зазвичай не повинні займатися проблемами, пов'язаними з вирівнюванням, про це повинні дбати розробники компілятора gcc. Однак такі проблеми все ж можуть виникати, коли розробнику доводиться виконувати операції з покажчиками, а також доступ до даних, не враховуючи того, як компілятор виконує операції доступу до даних.

char * p = dog [1];

unsigned long 1 = * (unsigned long *) p;

Якщо ви думаєте: "Навіщо мені це може бути потрібно? ', То ви, швидше за все, мають рацію. Проте, якщо ми таке зробили тільки що, то таке можна зробити і хто-небудь ще, тому необхідно бути уважними. Приклади, які зустрічаються в реальному житті, не обов'язково будуть так само очевидні.

Вирівнювання нестандартних типів даних

• Вирівнювання масиву виконується так само, як і вирівнювання типу даних першого елемента (всі інші елементи будуть коректно вирівняні автоматично).

• Вирівнювання об'єднання (union) відповідає вирівнюванню найбільшого, за розміром, типу даних з тих, які включені в об'єднання.

• Вирівнювання структури відповідає вирівнюванню найбільшого, за розміром, типу даних серед типів всіх полів структури.

У структурах також можуть використовуватися різні способи заповнення (padding).

Структури заповнюються таким чином, щоб кожен її елемент мав природне вирівнювання. Наприклад, розглянемо наступну структуру даних на 32разрядной машині.

char dog; / * 1 байт * / unsigned longcat; / * 4 байт * / unsigned shortpig; / * 2 байт * /

charfox; / * 1 байт * /

Ця структура даних в пам'яті виглядає не так, що пов'язано з необхідністю природного вирівнювання. У пам'яті компілятор створює структуру даних, яка схожа на наступну.

char dog; / * 1 байт * / u8 __pad0 [3]; / * 3 байт * / unsigned long cat; / * 4 байт * / unsigned short pig; / * 2 байт * /

char fox; / * 1 байт * /

u8 padl; / * 1 байт * /

Змінні заповнення вводяться для того, щоб забезпечити природне вирівнювання всіх елементів структури. Перша змінна заповнення вводить додаткові витрати пам'яті для того, щоб розмістити поле ca t на кордоні

Слід звернути увагу, що вираз sizeo f (foo_struct) дорівнює значенню 12 для будь-якого примірника цієї структури на більшості 32-розрядних апаратних платформ. Компілятор мови С автоматично додає елементи заповнення, щоб гарантувати необхідне вирівнювання.

Часто є можливість переставити поля структури так, щоб уникнути необхідності заповнення. Це дозволяє отримати правильно вирівняні дані без введення додаткових елементів заповнення і, відповідно, структуру меншого розміру.

struc t animal struc t

unsigned long cat; / * 4 байта * / unsigned short pig; / * 2 байта * / char dog; / * 1 байт * /

char fox; / * 1 байт * /

Ця структура даних має розмір 8 байт. Однак не завжди існує можливість перестановки елементів структури місцями і зміни визначення струк-

тури. Наприклад, якщо структура поставляється як частина стандарту, або вже використовується в існуючому коді, то порядок проходження полів міняти не можна. Іноді, з деяких причин, може знадобитися спеціальний порядок проходження полів структури, наприклад спеціальне вирівнювання змінних для оптимізації попадання в кеш. Зауважимо, що, згідно зі стандартом ANSI З, компілятор ніколи не повинен міняти порядок проходження полів у структурах5 даних - цим правом володіє тільки програміст.

Розробники ядра повинні враховувати особливості заповнення при обміні структурами даних: передача структур по мережі або безпосереднє збереження на диск, тому що необхідне заповнення може бути різним для різних апаратних платформ. Це одна з причин, по якій в мові програмування С немає оператора порівняння структур. Пам'ять, яка використовується для заповнення структур даних, може містити випадкову інформацію, що унеможливлює побайтово порівняння структур. Розробники мови, програмування С правильно зробили, що залишили рішення задачі порівняння структур на розсуд програміста, який може створювати свої функції порівняння в кожному конкретному випадку, щоб використовувати особливості побудови конкретних структур.

Схожі статті