Дана стаття у першій редакції була опублікована в журналі «Мой компьютер» (№22 (453))

Версія 2.4 від 18.10.2009 р.

Олександр Наталенко aka post-factum

mailto:pfactum@gmail.com

http://postfactum.pl.ua/

Володимир Кирилов aka Dark Proger

mailto:darkproger@gmail.com

http://darkproger.net/

У разі знаходження помилок в даній статті велике прохання повідомити про них за вказаними вище адресами.



Ядерна орнітологія

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

Маленьке попередження: якщо ви дійсно не знаєте, для чого вам потрібна перекомпіляція ядра - краще не робіть цього.

А для всіх інших почнемо.

Для початку вам, звичайно, необхідний вихідний код (source code, sources) ядра Лінукса. У складі вашого дистрибутиву він має бути, але його версія не обов'язково найновіша, оскільки виробни­ки дистрибутивів більше прагнуть надійності, аніж новизни, і тому використовують перевірені часом, але не найновіші ядра. Особисто я завжди віддаю перевагу останній версії. Цьому є кілька причин. По-перше, мною керує звичайна цікавість, по-друге, хочу знати, що в новому ядрі залатані дірки, а по-третє, люблю використовувати деякі його нові можливості. Наприклад, у ядрі 2.6.20 з'явилася підтри­мка віртуалізації, отже, якщо комусь ця штука необхідна (а останнім часом вона таки стає невід'ємною складовою побудови сучасного сервера), то без нового ядра не обійтися. Слід сказати, що додаються не тільки нові речі, а і вдосконалюються старі. Кому ж передусім важлива стабільність - є можливість використовувати старішу версію, зараз таким вимогам відповідає гілка 2.6.27 (кількість ядер у цій гілці складає вже 37, але слід пам’ятати, що нові можливості у це ядро не додаються, так само, як і підтримка нових пристроїв).

Кілька слів хотілося б сказати про попередню гілку ядра — 2.4.x. Остання версія, випущена на днях — 2.4.37.1. Навіть не знаю, чи доцільно її зараз використовувати будь-де. Мейнтейнер цієї гілки в листі, який анонсував останній стабілізаційний реліз, скептично відноситься до нього, говорячи, що варто поновлюватися, «…якщо цю гілку ще хтось використовує». Системним адміністраторам консервативного напрямку, які ще не визначилися, чи варто переходити на нову гілку, скажу однозначно, що варто хоча б тому, що старими гілками зараз ніхто не займається. Але, звісно, в першу чергу необхідно користуватися правилом «працює — не чіпай».

Отже, з версією ви визначилися. Для прикладу, візьмемо версію 2.6.31. Вам необхідно завантажити перше ядро цієї гілки, тобто власне 2.6.31. Ніколи не завантажуйте повністю вихідний код ядер, версія яких має вигляд 2.6.x.y - набагато простіше буде накласти патч (про це буде сказано далі), та і трафіку менше використовуватиметься, до того ж, процес пропатчування може йти у зворотну сторону — ви маєте змогу відмінити патч, отримавши початковий вихідний код. Пряме посилання на це ядро (57 Мб) http://kernel.org/pub/linux/kernel/v2.6/linux-2.6.31.tar.bz2.(інші ядра гілки 2.6 шукайте тут: http://www.kernel.org/pub/linux/kernel/v2.6/, каталогом вище ви можете знайти всі інші версії). Далі, з часом, для даної гілки з'являтимуться патчі, які, в принципі, нового нічого не додають, окрім виправлен­ня знайдених помилок (цим займається стабілізаційна команда). На момент написання статті останнім стабілізаційним патчем був четвертий (89 Кб): http://kernel.org/pub/linux/kernel/v2.6/patch-2.6.31.4.bz2.

Отже, після скачування ядра і основних патчів, необхідно подумати про патчі додаткові, якщо вам вони потрібні. Якщо ні – переходьте до безпосередньої конфігурації, компіляції та встановлення ядра.

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

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

Враховуючи свій досвід використання різних ядер, можу сказати, що проблеми у «ванільного» ядра дві: планувальник вводу-виводу та реалізація засипання комп’ютера зі зберіганням даних на жорсткий диск. У зв’язку з цим виділяю в першу чергу два основних патча:



Далі — більше.



Якщо вам хочеться усього і одразу, вам допоможуть патчсети:


Завантаживши всі патчі (або не завантаживши), приступаємо до процесу компіляції.

Для компіляції ядра вам потрібен компілятор gcc та інший «джентельменський» набір програм для розробки (напиклад, GNU make та binutils). Спосіб встановлення їх залежить від вашого дис­трибутиву (зверніться до документації або у пакетному менеджері вашого дистрибутиву, виберіть пункт «розробка», якщо такий є). Припустимо, у вас він вже встановлений.

Для початку нам необхідно отримати права суперкористувача (root). Це робиться командою «su» або «sudo -i» з подальшим вводом паролю. Далі запускаємо файловий менеджер Midnight Commander (команда «mc») і переходимо до директорії «/usr/src». Розпаковуємо туди tar.bz2-архів з вихідним кодом ядра. Найкраще це зробити тим же Midnight Commander'ом, який уміє працювати з рі­зними типами архівів. В результаті розпаковування має з'явитися директорія «linux-2.6.31» (нагадую, що для прикладу ми вибрали ядро 2.6.31 у вашому випадку версія може бути іншою). Це, звичайно, можна зробити за допомогою вашої командної оболонки власноруч, на ваш розсуд.

Є й інший варіант розпакування архіву – командою «tar -xjf linux-2.6.31.tar.bz2». Також мож­на використати спеціальну програму для полегшення розпакування – deco (це маленька про­грамка, яка використовує інші архіватори, сама знає, які параметри кому передавати, вам лишається лише вказати ім'я архіву).

Також буде розумно, якщо ви зробите символічне посилання з директорії «linux-2.6.31» на «/usr/src/linux», це допоможе вам у подальшому, якщо ви будете збирати програми з вихідних кодів, а та­кож допоможе вам не забути, де лежать коди вашого ядра. Але, якщо у вас декілька ядер, або ви їх постійно перезбираєте, то робити цього не варто.

Переходимо до цієї директорії, копіюємо до неї обрані патчі і розпаковуємо їх тим самим способом. Наприклад, ви обрали патч -pf3 (http://postfactum.pl.ua/nebula3/download.php?q=30159ec9add63ac6d18dbfe672e90768, 300 Кб). Файл «patch-2.6.31-pf3.bz2» розпаковується програмою bunzip2, в результаті чого ми отримуємо файл «patch-2.6.31-pf3». Тепер накладаємо патч командою «patch -p1 <patch-2.6.31-pf3». На екран буде виведено рядки, які потім слід продивитися і впевнитися у тому, що патч накладено вірно. Для того, щоб тимчасово вимкнути панелі Midnight Commander'а, слід натиснути комбінацію клавіш CTRL+O.

Невеликий коментар: не слід думати, що можна просто так взяти і накласти всі патчі, які у вас є. Вони не завжди сумісні один з одним (наприклад, на realtime-ядро неможливо накласти zen, та це і не потрібно).

Якщо процес накладання патча пройшов з помилками, про що програма повідомить, слід зверну­ти увагу на непропатчені файли. Якщо він один (а так найчастіше буває) - «Makefile», то швидше за все помилка виникла внаслідок того, що попередній патч до версії ядра дописав щось своє. Тоді може­те вручну відредагувати в цьому файлі рядок, який починається з «EXTRAVERSION = ». В принципі, це не суттєво.

Після накладання всіх патчів необхідно ядро сконфігурувати. Я не буду описувати кожну опцію ядра, бо у кожного користувача своє «залізо» і свої смаки. Одне скажу - аби ядро з вірогідністю 95% працювало після компіляції, можна використати конфігураційний файл від поточного ядра. Цей файл можна знайти або в директорії «/proc» («config.gz», стиснений файл конфігурації), якщо відповідна опція була увімкнена при компіляції старого ядра, або в директорії "/boot". Необхідно скопіювати його до нашої директорії (якщо він стиснений, то обов'язково розпакувати), перейменувати у «.config» і дати команду «make oldconfig». Запуститься консольне налаштування ядра, яке використає відповіді на більшість питань з готового конфігу, але будьте готовими відповідати на ті запитання, які стосуються нововведень у даному ядрі.

Якщо ви таки хочете конфігурувати ядро «з нуля» або хочете трохи змінити стару конфігурацію вашого ядра, давайте команду «make menuconfig». У цьому випадку вам буде представлений зручний псевдографічний інтерфейс у вигляді меню. Слід звернути увагу, що в цьому разі в системі мають бути встановлені бібліотеки ncurses і ncurses-devel.

Все ж таки дам кілька порад відносно конфігурування:

Завершивши конфігурування, запускайте компіляцію. Тут можливі два способи.

Найлегше тим, хто використовує Debian-based дистрибутиви, а також тим, хто на початку чи­тання передумав перезбирати ядро ;). Тут дається команда «CONCURRENCY_LEVEL=4 make-kpkg --initrd --append-to-version -blablabla kernel_image» (у вас має бути встановлений пакет kernel-package, а замість «blablabla» можете щось написати, наприклад своє ім'я, а можете не вказувати цей параметр взагалі), по завершенні якої ви матимете в директорії «/usr/src» готовий deb-пакет з ядром, який встановлює­ться командою «dpkg -i linux-image-2.6.31-pf3_2.6.31-pf3-10.00.Custom_i386.deb». Якщо ви використовуєте завантажник grub/grub2 (а рекомендується використовувати саме його, і ніякий більше), то просто перезавантажуйте комп'ютер, у меню завантажувача обирайте нове ядро і тестуйте.

Цікава змінна оточення CONCURRENCY_LEVEL. Якщо її задати так, як показано на прикладі, то процес компіляції буде проходити в кілька потоків, що дає суттєве скорочення часу збірки ядра. Екс­периментально спостерігається, що число потоків необхідно ставити як загальна_кількість_ядер_процесора(ів)*2. Якщо використовується патч BFS, то кількість потоків можна зменшити до кількості_ядер+1.

Також слід сказати про цікаву і корисну штуку під назвою DKMS (Dynamic Kernel Module Support). Цей набір скриптів значно полегшить процес встановлення нового ядра тим користувачам, у кого наявні сторонні модулі (наприклад, VirtualBox, broadcom-sta, kqemu і т. п.). Завдяки DKMS всі необхідні модулі автоматично перекомпілюються при перезавантаженні системи. DKMS особисто мною випробувана в Ubuntu (там, здається, взагалі всі модулі зав’язані на цю систему) та Debian’і. Спробую описати процес додавання якого-небудь модуля до цієї системи в дистрибутиві Debian.

Спочатку, звісно, варто встановити DKMS, виконавши команду «sudo aptitude install dkms».

Для прикладу візьмемо модуль broadcom-sta. По-перше, необхідно встановити вихідний код цього модуля за допомогою команди «sudo aptitude install broadcom-sta-source broadcom-sta-common» (у Debian Sid ці пакети зараз позначені як obsolete невідомо чому, тому, можливо, вихідні коди доведеться викачувати із офіційного сайту Broadcom). Далі необхідно зробити наступне символічне посилання (якщо у вас архітектура x86_64, то i386 необхідно замінити на amd64): «sudo ln -s /usr/src/modules/broadcom-sta/i386 /usr/src/broadcom-sta-5.10.91.9-1». Вказане значення версії некритичне, але воно зобов’язане бути присутнім через те, що DKMS вимагає особливого формату назви каталогів з вихідними кодами модуля.

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

Даємо команду «sudo vim /usr/src/broadcom-sta-5.10.91.9-1/dkms.conf» та пишемо:

BUILT_MODULE_NAME=wl

DEST_MODULE_LOCATION=/kernel/misc

PACKAGE_NAME=broadcom-sta

PACKAGE_VERSION=5.10.91.9-1

AUTOINSTALL=yes

Перший рядок — назва .ko-файлу, який і є власне модулем. Другий рядок можна не змінювати, він вказує на те, де буде зберігатися встановлений модуль. Ім’я та версію пишіть в залежності від Вашого модулю. Останній рядок відповідає за автовстановлення модулю, що нам, власне, і потрібно.

Переходимо в каталог «/usr/src» і виконуємо «dkms add -m broadcom-sta -v 5.10.91.9-1». Ця команда реєструє модуль і дає змогу DKMS перезбирати його при зміні ядра.

Тому, хто використовує не Debian чи Ubuntu, буде трохи важче зібрати ядро.

Спочатку дається команда «make -j 4» (параметр -j значить те ж саме, що і змінна CONCURRENCY_LEVEL), яка збере ядро і модулі. Потім дається команда «make modules_install», яка встановить модулі. А далі йде ручна робота. Під час компіляції ядра ви можете трохи відпочити, хоча не дуже довго (це залежить від швидкодії центрального процесора).

Готове ядро (файл bzImage) береться з піддиректорії "arch/x86/boot" (замість x86 може бути назва архітектури вашого комп'ютера; слід звернути увагу, що починаючи з версії ядра 2.6.24 архі­тектури i386 і x86_64 об'єднані в одну — x86, а для попередніх ядер каталоги різні) того каталогу, де у вас вихідні коди, і копіюється у директорію «/boot». Лише необхідно перейменувати даний файл, щоб його назва мала вигляд «vmlinuz-2.6.31-pf3-blablabla». Туди ж копіюється файл «System.map» і так само перейменовується на «System-2.6.31-pf3-blablabla.map».

Далі знову є кілька варіантів.

Можливо, у вас в системі наявна утиліта «update-initramfs». В такому разі запускаєте її: «update-initramfs -k 2.6.31-pf3-blablabla -c», і вона все зробить за вас.

В іншому випадку у вас має бути утиліта «mkinitrd». Запускаєте її так: «mkinitrd initrd-2.6.31-pf3-blablabla.img 2.6.31-pf3-blablabla». Хочу попередити, до речі, що ця команда в різних дис­трибутивах має різні параметри, і можливо, вам доведеться читати допомогу, щоб дізнатися її параметри (root-розділ, ім'я ядра, ім'я образу).

Хоча, якщо ви майже не збирали дуже важливі для вашої системи компоненти ядра як модулі, то initrd вам і не знадобиться.

У всякому випадку, припустимо, ви таки зробили все написане. Залишається налаштувати завантажувач. Припустимо, у вас grub. Тоді у файлі «/boot/grub/menu.lst» дописуємо такі рядки (ті­льки будьте впевненими у тому, що ви вказали правильний root-розділ; його можна взнати в цьому ж файлі, подивившись на записи, які стосуються старого ядра):

title

Debian GNU/Linux, 2.6.31-pf3-blablabla

root

(hd0,1)

kernel

/boot/vmlinuz-2.6.31-pf3-blablabla root=/dev/sda2 ro

initrd

/boot/initrd.img-2.6.31-pf3-blablabla

Наведена конфігурація справедлива для grub-legacy, тобто для першої, вже застарілої, але ще активно використовуваної гілки grub. В Debian Sid почався перехід на grub2. З власного досвіду можу сказати, що працює він нормально.

Якщо у вас grub2 (як, наприклад, у мене), то конфігурація буде змінюватися у файлі «/boot/grub/grub.cfg» і матиме вигляд:

menuentry "Debian GNU/Linux, Linux 2.6.31-pf3-blablabla" {

set root=(hd0,2)

search --no-floppy --fs-uuid --set 19fe5a10-df62-45a2-8d66-86e32aaee425

linux /boot/vmlinuz-2.6.31-pf3-blablabla root=/dev/sda2 ro

initrd /boot/initrd.img-2.6.31-pf3

}

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

Для абсолютно лінивих людей, яким просто не хочеться/не можеться робити зазначені речі вру­чну, придумана команда «make install». Вона автоматично встановлює ядро і модулі, а також прописує необхідні параметри, взяті з попереднього ядра, у конфігураційному файлі завантажувача. Стовідсо­тково, однак, на цю команду покладатися не варто, і після неї все необхідно перевірити вручну, щоб мати змогу завантажити систему у будь-якому разі, навіть якщо ядро недієздатне.

На цьому все. Пишіть, як щось незрозуміло.

P. S. Окремо велике спасибі Олегу Точенюку (Uukrul), alexeywww, Сергію Бурачеку (Bur), Олегу Матвійчуку (Mathway), Володимиру Колибенку (Druik), Костянтину Ільченку (dj_doom), Володимиру Пузанову (Farcaller), Jan2ary, elips’у за допомогу при написанні даної статті.

P. P. S. Автори не несуть відповідальності за втрату даних, вихід із ладу обладнання комп'ютера або психіки людини після читання та виконання дій за цією статтею, навіть якщо в ній є помилки. Тобто, «no warranty».

P. P. P. S. Linux forever!