Стиль написання вихідного коду

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

Поки стиль ще не вибрано і широко не використовується, не так важливо, який саме стиль вибрати На щастя, ще дуже давно Лінус представив на розгляд стиль, який необхідно використовувати, і при написанні більшої частини коду зараз намагаються дотримуватися саме цього стилю Детальний опис стилю приведено у файлі Documentation / CodingStyl e з властивим Лінусу гумором

Відступи

Для вирівнювання тексту і введення відступів використовуються символи табуляції Розмір одного символу табуляції при відображенні відповідає восьми позиціях Це не означає, що для структурування можна використовувати вісім чи чотири символи пробіл або що-небудь ще Це означає, що кожен рівень відступу дорівнює одному символу табуляції від попереднього і що при відображенні довжина символу табуляції дорівнює восьми символам З незрозумілих причин, це правило майже завжди порушується, незважаючи на те що воно дуже сильно впливає на читабельність Восьмісімвольная табуляція дозволяє дуже легко візуально розрізняти окремі блоки коду навіть після декількох годин роботи

Якщо табуляція у вісім символів здається дуже великою, то не потрібно робити так багато вкладень коду Чому ваші функції мають пять рівнів вкладеності Необхідно виправляти код, а не відступи

Фігурні дужки

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

розробці ядра – це розміщувати відкриває дужку в першому рядку, відразу за відповідним оператором Закриває дужка поміщається в першій позиції з нового рядка, як у наступному прикладі

if (fox) {

dog()

cat()

}

У разі, коли за закриває дужкою триває те ж саме вираз, то продовження вираження записується в тому ж рядку, що й закриває дужка, як показано нижче

if (fox) {

ant()

pig()

} else {

}

dog()

cat()

або таким чином

do {

dog()

cat()

} while (fox)

Для функцій це правило не діє, тому що всередині однієї функції тіло іншої функції описувати не можна

unsigned long func(void)

{

/* . */

}

І нарешті, для виразів, в яких фігурні дужки не обовязкові, ці дужки можна опустити

if (foo)

bar()

Логіка всього цього базується на K & R1

Довгі рядки

При написанні коду ядра необхідно намагатися, наскільки це можливо, щоб довжина рядка була не більша 80 символів Це дозволяє рядкам, при відображенні на терміналі розміром 80×24 символу, вміщуватися в одну дію терміналу

1 Брайен н У Керниган, Денні з М Рітчі, Мова програмування С, 2-е вид Пер з англ – М: Видавництво будинок Вільямові, 2005

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

Деякі розробники поміщають параметри функції один під одним, якщо параметри не поміщаються в одному рядку, як у наступному прикладі

static void get_pirate_parrot(const char *name, unsigned long disposition, unsigned long feather_quality)

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

int find_pirate_flag_by_color(const char *color, const char *name, int len)

Оскільки на цей рахунок немає певного правила, вибір залишається за розробниками, тобто за вами

Імена

В іменах не можна використовувати символи різних регістрів Назвати змінну імям idx, або навіть i – це дуже добре, але за умови, що буде зрозуміло призначення цієї змінної Занадто хитрі імена, такі як theLoopIndex, неприпустимі Так звана угорська запис (Hungarian notation), коли тип змінної кодується в її імені, У даному випадку – ознака поганого тону Це С, а не Java і Unix, а не Windows

Проте, глобальні змінні і функції повинні мати наочні імена Якщо глобальної функції присвоїти імя atty (), то це може призвести до плутанини Більш підходящим буде імя gs t a c t i v e t t y () Це все-таки Linux, а не BSD

Функції

Існує мнемонічне правило: функції не повинні за обсягом коду перевищувати двох екранів тексту і мати більшедесяти локальних змінних Кожна функція повинна виконувати одну дію, але робити це добре Чи не шкідливо розбити функцію на послідовність більш дрібних функцій Якщо виникає занепокоєння з приводу накладних витрат за рахунок виклику функцій, то можна використовувати підстановку тіла – inline

Коментарі

Дуже корисно використовувати коментарі коду, але робити це потрібно правильно Зазвичай необхідно описувати,що робить код ідля чого це робиться Те,якреалізований алгоритм, описувати не потрібно, це має бути ясно з коду Якщо так зро-

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

У ядрі використовуються коментарі в стилі С, хоча компілятор gcc підтримує також і коментарі в стилі C + + Зазвичай коментарі коду ядра повинні бути схожі на наступні (лише англійською мовою, звичайно)

/*

* Get_ship_speed () повертає поточне значення швидкості

* Піратського корабля

* Необхідна для обчислення координат корабля

* Може переходити в стан очікування,

* Не можна викликати при утримуваної блокуванні

*/

Коментарі всередині функцій зустрічаються рідко, і їх потрібно використовувати тільки в спеціальних ситуаціях, таких як документування дефектів, або для важливих зауважень Важливі зауваження часто починаються з рядка XXX:, а інформація про дефекти-з рядка FIXME:, як у наступному прикладі

/*

* FIXME: Вважається, що dog == cat

* У майбутньому це може бути не так

*/

У ядра є можливість автоматичної генерації документації Вона заснована на GNOME-doc, але трохи модифікована і називається Kernel-doc Для створення документації в форматі HTML необхідно виконати наступну команду

make htmldocs

Для генерації документації у форматі postscript команда повинна бути наступною

make psdocs

Документувати код можна шляхом введення коментарів у спеціальному форматі

/**

* Find_treasure знаходження скарбів, помічених на карті хрестом

* @ Map карта скарбів

* @ Time момент часу, коли були зариті скарби

*

* Повинна викликатися при утримуваної блокуванні pirate_ship_lock

*/

void find_treasure (int dog, int cat)

{

/* . */

}

Для більш детальної інформації див файл Documentation / kernel-doc-nanoHOWTOtxt

Використання директиви typede f

Розробник і ядра не люблять визначати нові типи за допомогою оператор а typedef, і причини цього досить важко пояснити Розумне пояснення може бути наступним

• Визначення нового типу через оператор typede f приховує справжній вигляд структур даних

• Оскільки новий тип виходить прихованим, то код більш схильний таким нехорошим речам, як передача структури даних у функцію за значенням, через стек

• Використання оператора typede f – ознака ліні

Щоб уникнути насмішок, краще не використовувати оператор typedef

Звичайно, існують ситуації, в яких х полезн про іспользоват ь операто р typedef: приховування специфічних для апаратної платформи деталей реалізації або забезпечення сумісності при зміні типу Потрібно добре подумати, чи дійсно оператор typede f необхідний або він використовується тільки для того, щоб зменшити кількість символів при наборі коду

Використання того, що вже є

Не потрібно винаходити паровозЯдро надає функції роботи з рядками, підпрограми для стиснення і декомпресії даних та інтерфейс роботи зі звязаними списками – їх необхідно використовувати

Не потрібно инкапсулировать стандартні інтерфейси в інші реалізації узагальнених інтерфейсів Часто доводиться стикатися з кодом, який переноситься з інших операційних систем в систему Linux, при цьому на основі існуючих інтерфейсів реалізується деяка громіздка функція, яка служить для звязку нового коду з існуючим Таке не подобається нікому, тому необхідно безпосередньо використовувати надані інтерфейси

Ніяких директив ifde f у вихідному коді

Використання директив препроцесора ifde f у вихідному коді категорично не рекомендується Ніколи не слід робити чогось на кшталт такого

#ifdefconfig_foo foo()

#endif

Замість цього, якщо макрос CONFIG_FOO не визначений, необхідно визначати функцію FОО (), както, яка нічого не робить

tifdefCONFIG_FOO

static int foo(void)

{

/* . */

}

#else

static inline int foo(void) { }

#endif

Після цього можна викликати функцію foo () без жодних умов Нехай компілятор попрацює за вас

Ініціалізація структур

Структури необхідно ініціалізувати, використовуючи мітки полів Це дозволяє запобігти некоректну ініціалізацію при зміні структур Це також дозволяє виконувати ініціалізацію НЕ всіх полів На жаль, в стандарті С99 прийнятий досить страшненький формат міток полів, а в компіляторі gcc раніше використовувався формат міток полів у стилі GNU визнаний застарілим Отже, для коду ядра необхідно використовувати новий формат, відповідно до стандарту С99, яким би жахливим він не був

struct foo rny_foo = {

. А = INITIAL_A,

. Ь = INITIAL_B,

}

де а і b – це поля структури struc t foo, а параметри INITIAL_A і INITIAL_B – відповідно, їх початкові значення Якщо поле не вказано при ініціалізації, то воно встановлюється в своє початкове значення, відповідно до стандарту ANSI С (вказівниками присвоюється значення NULL, цілочисловим полях – нульове значення, а нолям з плаваючою точкою-значення 00) Наприклад, якщо структура struc t foo також має поле in t с, то це поле в попередньому прикладі ініціалізується в значення 0

Так, це жахливо Але у нас немає іншого вибору

Виправлення раніше написаного коду

Якщо у ваші руки потрапив код, який навіть близько не відповідає стилю написання коду ядра Linux, то все одно не варто втрачати надії Трохи завзяття, і утиліта inden t допоможе зробити все як треба Програма inden t – відмінна утиліта GNU, яка включена в багато поставки ОС Linux і призначена для форматування вихідного коду відповідно до заданих правил Установки за замовчуванням відповідають стилю форматування GNU, який виглядає не дуже красиво Для того щоб утиліта виконувала форматування відповідно до стилю написання коду ядра Linux, необхідно використовувати наступні параметри

indent-kr-i8-ts8-sob -180-ss-bs-psl <файл>

Можна також використовувати сценарій scripts / Lindent, який викликає утиліту inden t з необхідними параметрами

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

Схожі статті:


Сподобалася стаття? Ви можете залишити відгук або підписатися на RSS , щоб автоматично отримувати інформацію про нові статтях.

Коментарів поки що немає.

Ваш отзыв

Поділ на параграфи відбувається автоматично, адреса електронної пошти ніколи не буде опублікований, допустимий HTML: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

*

*