Отстраняване на грешки и тестване на модули на ядрото, част 77
В тази последна статия за характеристиките на модулите за програмиране на ядрото ще разгледаме един важен въпрос, който, макар и да не е пряко свързан с разработката, може да окаже значително влияние върху нея – изграждането и инсталирането на персонализирана версия на ядрото. Противно на общоприетото схващане, не е необходимо да се изгражда модифицирано ядро, за да се създаде среда за разработка на модули. Освен това тази операция не трябва да се извършва без основателна причина. Но има случаи, когато трябва да прибягвате до инсталиране на специализирана версия на ядрото, например, за да зададете (активирате) необходимия набор от конфигурационни параметри за отстраняване на грешки.
Актуализация на ядрото
Ако се интересуватесамо от актуализиране на версията на ядрото на работеща система, тогава най-добрият начин да направите това е да актуализирате ядрото с пакетна система отхранилището на вашата дистрибуция. Например за дистрибуции на RedHat / Fedora / CentOS списъкът с актуализации може да бъде получен по следния начин:
Остава да инсталирате тези пакети, които искате да актуализирате и да завършите четенето на тази статия. Но ако искате да знаете как да изградите ядрото за вашите собствени нужди, продължете да четете.
Възстановяване на ядрото
След това ще разгледаме ситуации, в които наистина е необходимо да се изгради ново ядро от източниците на ядрото на Linux. Знам за доста ограничен списък от сценарии (възможни при изграждане на модули на ядрото), които всъщностизискват повторно изграждане на ядрото:
За да разрешите последния проблем, може да се наложи да компилирате няколко последователни версии на ядрото със същите конфигурации и да тествате модула в инсталации на тези ядра във виртуални машини, за да проверите за съвместимост.
Компилирането, изграждането и инсталирането на ядрото е описано стотици пъти в интернет публикации. Но ще се спрем на някои подробности, които са особено важни от гледна точка на програмист на модули на ядрото, но не са съществени за системния администратор, когато компилира ядрото за своите задачи (най-често при опити за оптимизация, което отново е маловажно за нашите цели).
Можете да изградите ядрото навсякъде във файловата система: в/usr/src (като почит към традицията), домашната директория на потребителя, в директорията за компилация на пакета на ядрото, предварително дефинирана от спецификацията за компилация (
/rpmbuild), или където и да е другаде.
Откъде идва кодът на ядрото?
- ако изграждаме текущото (по версия) ядро, но с променени параметри (например, за да разрешим опциите за отстраняване на грешки в ядрото), тогава ще се опитаме да използваме изходния код на ядроторазпределение и неговата конфигурация като отправна точка за промени.
- ако компилираме по-ново ядро (за проверка и тестване), тогава не ни е позволено да прилагаме пачове, предназначени за старата версия, към изходния код на по-новото ядро, в който случай вземамеофициалния код на ядрото.
За по-лесно разбиране ще разгледаме тези възможности в обратен ред.
Официално ядро
Ако сте получили кода на по-ранни версии (преди 3.04) под формата на архив, тогава той трябва да бъде разширен в дърво на източника. За категоричност ще приемем, че дървото е разширено и разархивирано в директорията/usr/src :
Удобно е веднага да направите символна връзка на същото място (/usr/src ) с иметоlinux към директориятана тези работещи изходни кодове, като най-нова опция. След това, с последващи промени във версията на ядрото, можете само да пренаредите връзката. Сега имаме изходно дърво за по-нататъшни действия:
Показано е общото количество изходни кодове на ядрото, към което ще се върнем.
Ядро от хранилище за разпространение
Повечето дистрибуции съдържат в своите хранилища, в допълнение към софтуерните пакети, изходния код на ядрото на дистрибуцията, но често този пакет не е в основното хранилище. Ще ви покажа как да получите и използвате ядрото на дистрибуцията с корекции, използвайки дистрибуцията Fedora (за RPM дистрибуции) като пример. Други дистрибуции следват подобен процес и общият принцип тук е, че трябва да пресъздадете от изходния пакет същото дърво на изходния код, от което пакетът е изграден от създателя на пакет (в този случай rpmbuild). Нека направим това със следните стъпки.
Първо, нека създадем обща структура за изграждане на всеки пакет, преди да бъде зареден. Моля, обърнете внимание, че пътят на изградената структура на директория не зависи от мястото, където изпълняваме командата, а зависи от името на потребителя, който е стартирал командата: дървото на директорията се създава в домашната директория на този потребител ($HOME/rpmbuild ):
Вече можете да изтеглите изходния пакет от хранилището на дистрибуцията, но на тази стъпка може да се наложи да деактивирате или добавите допълнителни хранилища:
След това разрешаваме зависимости, т.е. инсталираме софтуерни пакети, които са посочени като необходими за работа с това ядро, въпреки че няма да ни трябват, но това е правилният подход:
Всички тези стъпки бяха подготвителни и сега инсталираме пакета в дървото
/rpmbuild (може да има много предупреждения за потребителя и групата на създателя на пакети, но това може да бъде игнорирано):
На този етап вече имаме:
- в директорияSOURCES архив с изходен код и много (150) файла с корекции(*.patch ) към него;
- в директориятаSPECS спецификация на пакета;
- в момента празна директорияBUILD, в която се извършва сглобяването.
Имайте предвид, че архивът на изходния код (в директориятаSOURCES ), показан в тази стъпка, еофициален архив, точно същият като този, получен в предишния преглед.
Разполагаме (изграждаме) пакета за текущата архитектура в оригиналната форма, от която е създаден. Когато създавате пакет, всички горепосочени корекции се прилагат към оригиналното ядро.
Сега, в наскоро празна директория, имаме 530MB изходно дърво или по-точно две дървета: официалното дърво (ванилия, което беше споменато по-рано) и същото дърво, което е закърпено от създателите на дистрибуция:
Дървото на разпространението също е различно по това, че съдържа много конфигурационни файлове, за които е изградено това разпространение, и дори отделна директорияconfigs. Това е добра отправна точка за нашата бъдеща конфигурация на изграждане. И няма конфигурационни файлове в официалното дърво на конфигурационните файлове:
Копирайте конфигурационния файл, съответстващ на нашата архитектура, вместо текущия.config файл:
И ние декларираме това ново съдържание като конфигурационен файл на ядрото:
В този момент сме достигнали същото състояние в това дърво, в което оставихме дървото, изтеглено от официалния сайт на ядрото на Linux, и можем да продължим към конфигурацията на новото ядро (и в двата случая).
Конфигурация
Сега трябва да направим конфигурацията на ядрото, което трябва да доведе до създаването на файла./config в изходната директория. Добра идея е да използвате файла./config като първоначално приближение, според коетоизгради текущото работещо ядро. Обикновено копие на този файл (преименуван с името на ядрото) се съхранява в директорията/boot :
Тази система (пример) има инсталирани две алтернативни ядра (две опции за зареждане). Един от тези файлове е конфигурацията на работещата система и може да бъде копиран под името./config в изходната директория.
Преди да стартирате конфигуратора, почистете директорията от следи от предишния монтаж:
На този етап можете да промените един (4-ти) ред вMakefile, като го промените:
Това ще накара генерираното ядро (и всички придружаващи файлове) да бъде нареченоlinux-2.6.37.3-myOWN (т.е. конкатенация на версията на ядрото със суфиксаEXTRAVERSION), което улеснява разграничаването между собствените модификации.
Нека да преминем към задачата за конфигуриране. Имаме няколко цели, от които да избираме вMakefile за конфигуриране:
Нека стартираме графичния конфигуратор:
Стартирах графичния конфигуратор в GNOME, така че избрахgconfig, но ако използвате KDE, трябва да използвате конфигуратораxconfig.
Фигура 1 показва резултата от стартирането на графичния конфигуратор.
Фигура 1. GUI на Linux Kernel Configurator


След завършване на конфигурацията с помощта на GUI, показан на фигура 1, ще получим съобщение:
Което означава, че ядрото е конфигурирано и можем да започнем да го изграждаме.
Тук можете да проверите отново дали създаденият конфигурационен файл.config се различава от копирания преди това от директорията/boot както по размер, така и по време и дата на създаване.
Компилация
Компилирането на ядрото отнема много времеоперация и на 2-ядрен 1,6 GHz процесор процесът на компилиране на ядрото отне около 25 минути:
След това ще компилираме модулите на ядрото и този процес ще отнеме още четири пъти повече време!
Нека отново измерим пространството, заето от файловете в изходната директория:
Обемът след компилация се увеличи с почти 2GB (вижте фигурата по-рано). Подобно количество свободно пространство трябвада има на диска за успешна компилация на ядрото. Обръщам внимание на факта, чевсички операции до този момент бяха извършени без root права!
Нека инсталираме модулите на ядрото (и сравним съдържанието на директорията/lib/modules преди и след инсталацията):
И така, директорията на модула на новата версия се появи:/lib/modules/2.6.37.3 и крайният размер на изградените модули се оказа не толкова голям. Нека инсталираме вграденото ядро (и сравним съдържанието на директорията/boot преди и след инсталацията):
Имаме 3 нови файла
- vmlinuz-2.6.37.3 —ядро;
- initramfs-2.6.37.3.img - изображение на първоначалната стартираща система;
- System.map-2.6.37.3 е символната таблица на новото ядро.
Инсталирането на ядрото 2.6.37.3 в примера правилно редактира файла на менюто за стартиране/boot/grub/grub.conf на GRUB буутлоудъра, така че след рестартиране системата ще стартира със същите настройки, с които е стартирала преди:
За съжаление GRUB буутлоудърът не винаги може правилно да редактира менюто за конфигурация при стартиране. Но това изобщо не е трудно и можете да редактирате стартовото меню/boot/grub/grub.conf, за да отговаря на нуждите на конкретен проект.
Как да ускоря изграждането на ядрото
Един от основните фактори, влияещи върху времето за изграждане на ядрото, е скоростта на твърдия диск при запис на голям бройкратки обектни файлове. Но хардуерът на много компютри ви позволява да използватеtmpfs (RAM диск) като устройство за съхранение за изграждане:
Нека проверим тази възможност, като копираме дървото на източника в директорията/dev/shm :
Както можете да видите, времето за изграждане на ядрото беше намалено до 10 минути (2,5 пъти), което е много добре.
Друг начин за значително ускоряване на изграждането на ядрото е да кажете на помощната програма make да използва всички налични процесорни ядра при изграждане на ядрото:
Или, ако искате да посочите конкретен брой ядра (например 4), участващи в процеса на изграждане:
Но бъдете внимателни с този метод! Не всички версии на ядрото завършват успешно при паралелно използване на множество процесори, което може да се дължи на неправилна синхронизация на клонове по време на компилация. Но експерименталната проверка на такава възможност не вреди по никакъв начин.