Зачем собирать ядро linux

Обновлено: 01.07.2024

Зачем пересобирать ядро? Обычно этого делать не нужно, так как ядро, устанавливаемое по умолчанию в современных дистрибутивах, подходит для многих конфигураций. Однако, полезно пересобрать ядро в следующих случаях:

  • если установлено специфичное оборудование или возникает конфликт аппаратного обеспечения со стандартным ядром;
  • чтобы задействовать свойства, которых нет в поставляемых сборках ядра;
  • для оптимизации ядра, удаляя ненужные драйверы для уменьшения времени загрузки;
  • создания монолитного ядра, без модулей;
  • для установки обновлённого или разрабатываемого ядра;
  • чтобы больше узнать о ядрах Linux.

В стародавние времена приходилось регулярно перекомпилировать ядра.

Способы

Стандартное расположение исходников ядра — /usr/src. Однако обычно предпочтительнее собирать ядро от имени непривилегированного пользователя в $HOME, затем устанавливать в систему от имени суперпользователя.

Сборка современных версий ядер (в зависимости от конфигурации) требует около 15 ГБ места на диске. В ядре более 20 млн строк кода.

E2b0fac8e29ba3ebdb4116330cf5acea76ef73d4.jpg

Классический путь

Способ универсален, но имеет некоторые недостатки. Например, затруднено удаление ядра: после установки нужно вручную удалять файлики

  • /boot/vmlinuz*KERNEL-VERSION*
  • /boot/initrd*KERNEL-VERSION*
  • /boot/System-map*KERNEL-VERSION*
  • /boot/config-*KERNEL-VERSION*
  • /lib/modules/*KERNEL-VERSION*/
  • /var/lib/initramfs/*KERNEL-VERSION*/

Debian-способ

Управлять ядрами с помощью системы управления пакетами на самом деле безопаснее и легче.

Другие диструбутивоспецифичные способы

Практика

Будем экспериментировать на ОС Ubuntu.

Скачиваем свежий ванильный архив с официального сайта:

Скорее всего, нужно будет доустановить некоторые пакеты.

Чтобы воспользоваться консольным конфигуратором, понадобится библиотека для псевдографики:

make oldconfig

Берёт существующий конфиг (либо из файла .config в корне исходников ядра, либо из /boot/ для той версии ядра, которая используется в данный момент) и выставляет новые опции (на выбор пользователя или по умолчанию).

Если вопросов много и мы не хотим отвечать, можно везде брать значение по умолчанию:

make olddefconfig

Аналогичная команда, строит новый конфиг на базе старого, новые опции ставятся по умолчанию.

make menuconfig

Имеет псевдографический интерфейс в виде меню. Программа основана на библиотеке ncurses.

Для интереса выставим в General Setup -> Local version значение -bsu.

make localmodconfig

Выбрать, какие модули собирать в составе ядра, на основе работающей хост-системы [1].

Поехали!

Недолго музыка играла.

Ищем, какой пакет доустановить.

Возможно, придётся ещё что-то доустановить.

Наконец, всё должно собраться:

Установка ядра

Разместит *.ko-файлы в /lib/modules.

Разместит файлы в /boot/.

Ужас, рамдиск получился огромный! Оказывается, надо было при установке передавать опцию INSTALL_MOD_STRIP=1.

sudo chmod 777 /usr/src

После этого, забрасываем его (скачанный архив) в папку /usr/src. Распаковываем архив командой:

tar -jxvf xxxxx.tar.bz2

Далее, перед сборкой ядра необходимо установить сопроводительные пакеты: gcc, libc6-dev, kernel-package, libncurses5-dev, fakeroot и build-essential.

Когда все установлено и изучено, можно приступать собственно к конфигурированию ядра.

Заходим в директорию /boot, и видим там файл примерно такого названия config-2.6.24-19-generic. Он нам и нужен. Копируем его в каталог с исходниками /usr/src/xxxxx и переименовываем его в .config.

Далее запускаем конфигуратор ядра, для чего, находясь в папке /usr/src/xxxxx, даем команду:

Эта команда запускает консольный интерфейс настройки. Ежели вам более по душе графический конфигуратор, то для его запуска нужно использовать команду:

Есть еще вариант консольной настройки:

Этот вариант очень полезен только тогда, когда уже имеется сформированный файл настроек .config (можно использовать файл настроек от старого ядра). В этом варианте задаются только вопросы по возможностям, появившимся с той версии ядра, для которой сделан файл настроек.

diff .config .config_mykernel

Теперь копируем вашу конфигурацию .config_mykernel как .config. Т.е. у вас получится три файла конфигурации. При компиляции будет использоваться файл .config. Файлы .config_ubuntu и .config_mykernel нам помогут в будущем для новой компиляции. Это на тот случай, если новое ядро окажется неработоспособным.

Далее приступим к компиляции. Перед этим, нужно очистить мусор командой:

Компиляцию ядра стоит делать под суперпользователем. Для чего становимся рутом и запускаем процесс сборки ядра:

в этой строчке mykernel.1 обозначает название ядра. Можно писать все что душе угодно.

По окончании процесса создадутся два deb-файла с ядром, сконфигурированным конкретно под ваши нужды. Поздравляю, ядро готово.

Теперь необходимо установить собранное ядро в систему:

sudo dpkg -i linux-image-xxxxx.deb
sudo dpkg -i linux-headers-xxxxx.deb


Любой программист знает, что теоретически он может внести свой посильный вклад в развитие Linux ядра. С другой стороны, подавляющее большинство уверено, что занимаются этим исключительно небожители, а процесс контрибьюта в ядро настолько сложен и запутан, что обычному человеку разобраться в нём нет никакой возможности. А значит, и надобности.
Сегодня мы попробуем развеять эту легенду и покажем, как абсолютно любой инженер при наличии достойной идеи, воплощённой в коде, может предложить ее на рассмотрение Linux community для включения в ядро.

0. Подготовка

Как и перед любой инженерной операцией, всё начинается с подготовки своего рабочего места. И первейшее здесь действие — это завести себе аккаунт с адекватным именем. В идеальном мире это будет просто транскрипция имени и фамилии. Если за учётку вроде MamkinC0d$r или Developer31337 в других местах пальцем в вас тыкать не будут, то правила LKC (Linux kernel community) такое прямо запрещают — инкогнито контрибьютить в ядро не принято.

Далее вам понадобится место на локальной машине. Сама папка Linux со скачанными исходниками весит чуть меньше 3-х гигов. Но если ядро пробовать собирать, то вместе с модулями займёт все 30 GB.

Захотелось собрать несколько веток? Умножаем 30 на число веток.
И помним — скорость сборки прямо связана с количеством доступных ядер! Больше ядер — быстрее соберётся. Так что не стесняйтесь выделять под это самую мощную машину.

1. Mail

Вокруг необходимости делать всё через плейнтекст в почте есть масса споров. Недавно в сети была очередная громкая статья на эту тему. Суть материала: письма — это, конечно, здорово, но пихать туда всё, включая куски кода — это вам (т.е. LKC) популярности не добавляет и даже наоборот, отпугивает новичков. С одной стороны вроде и да, если ты не можешь спокойно и структурировано изложить свои мысли в голом тексте, то в низкоуровневой разработке ловить будет особо нечего. С другой стороны, слать в письмах сорсы патчей — это даже архаизмом назвать уже сложно.

Но, как принято в уютном мирке ядра, Линус хлопнул кулаком по столу — и все пишут письма. Возможно, буквально завтра это изменится, но на момент выхода статьи это письма и только письма.

Какой email-client выбрать — есть рекомендации. Самым рекомендуемым почтовым агентом для LKC остаётся mutt. Да, тот самый текстовый почтовый клиент, от которого сводит олдскулы. Для начала mutt нужно поставить (я думаю, со своим пакетным менеджером вы и сами справитесь), а потом задать параметры в файле

Но почты недостаточно. Без Git никуда.

2. Git

Прежде чем что-то делать с исходниками ядра, нужно настроить Git. Можно конфигурировать файлы напрямую, но есть упрощающая жизнь утилита git config, через которую можно регулировать все аспекты работы Git'a.

Внутри есть три уровня настроек: общие для всех пользователей системы и для всех репозиториев (git config --system), общие для всех репозиториев конкретного пользователя (git config --global), отдельные для каждого репозитория (git config --local).

Глобальные настройки хранятся в /etc/gitconfig, настройки пользователя в

/.config/git/config, а настройки отдельных репозиториев хранятся в файле config в каталоге .git/config.

В общем случае будет достаточно законфигурировать файл для пользователя

/.gitconfig . Основная идея: при отправке коммитов должно отображаться ваше корректное имя.

signOff обязателен, чтоб в коммитах была информация об авторе. По идее, надо бы, чтобы коммиты подписывались. Была тут недавно статья на эту тему.

Отправка патча выполняется командой git send-email. У git send-email есть несколько параметров с участием smtp, которые можно (и нужно) переопределить.

Можно задавать пароль к почте через параметр --smtp-pass=p4ssw0rd или вообще захардкорить в конфиге, но это это для тех, кому терять нечего. Но если каждый раз вводить пароль лень, то есть некий хак: если username был задан (через --smtp-user или sendmail.smtpUser), а пароль не указан, тогда пароль получается через git-credential.

Итак, окно в большой мир прорубили. Можно переходить к воплощению своей грандиозной идеи в коде.

3. Coding

Итак, мы готовы сделать первый шаг непосредственно в разработке — склонировать к себе репозиторий. Советую делать это сразу с указанием ветки, которая будет создана. Также отмечу, что работать лучше не над текущим состоянием в master, а над стабильной версией или кандидатом на релиз. Так вы будете более уверены, что ядро соберётся и будет как-то работать, не вызовет неожиданных конфликтов из-за изменений в других подсистемах. Поэтому всегда внимательно смотрите тэги.

И — опять же — имя своей ветке постарайтесь дать чёткое и лаконичное. В идеальном мире оно даже может отображать суть вносимых изменений. Если вы исправляете известный баг, то хорошим тоном считается включить в название ветки номер issue.

Операция довольно долгая, так что смело можно идти за кофе или на обед. А если попробовать ускорить процесс, отказавшись от истории, то работать с "этим" будет невозможно.

Итак, мы получили ветку, в которой можно начинать свою разработку. Здесь всё очевидно: пишем код, собираем, тестируем, исправляем баги — и так до получения нужного результата. О том, как собирать ядро и проводить отладку, информации в сети море, так что подробно описывать весь процесс я не буду. Лишь вкратце пробежимся по нему чуть позже. Единственный нюанс, который добавлю от себя прямо сейчас: перед сборкой проверьте наличие всех необходимых программ из этого списка и их минимальные версии.

Если бродить вслепую по гуглу не хочется, то вся максимально полезная информация по ядру сконцентрирована тут. Прочитать стоит действительно всё. Особенно правильно будет начать с How To о том, как правильно коммуницировать. Потому что мейнтейнеры, как правило, люди весьма занятые, и вникать в невнятно составленные письма им никакого интереса. Да и вам будет обидно, если из-за плохого описание ваше детище не примут в апстрим.

И вот свой небольшой и эффективный код вы написали, отладили, всё протестировали и готовы отправлять на рассмотрение. Но не спешите этого делать. Для начала обязательно проверьтесь на code style. В этом вам поможет ./script/checkpatch.pl . Для этого сделаем патч и отправим его на проверку.

После того, как пройдёт первое удивление и вы доустановите необходимые компоненты для python2 типа ply и git (который у меня так и не установился), наступит чудесное время исправления ошибок и ворнингов. По результатам которых вы а) поймёте, что красивый код писать вы не умеете б) потеряете всякое желание что-то куда-то отправлять. Ведь даже если отбросить все шутки, ещё можно как-то смириться с тем, что длина строк ограничена 100 символами (это начиная с версии 5.7, раньше так было вообще 80). Но вот такие места оставляют неизгладимое впечатление:

Для .h файлов строка с информацией о лицензии должна быть в ремарках / * */, а для *.c файлов должна быть в ремарках //. Такое запросто выбьет кого угодно из душевного равновесия. Вопрос: "Зачем?!" до сих пор болтается в моей голове, хотя есть вера в то, что это не просто ошибка в скриптах.

Кстати, чтобы просто проверить один файл достаточно вызвать

Можно прикрутить этот вызов к git, чтобы автоматически запускался этот скрипт при попытке что-то зачекинить.

Ещё важное замечание: clang-format добрался и до ядра Linux. Файл .clang-format расположился в корне ядра в кучке с другими конфигами. Но я не советую добавлять его в хук для git. Лучше всего корректно настроить среду разработки и запомнить code style. Лично мне не понравилось как он делает переносы длинных строк. Если вдруг строка оказалась длиннее допустимой, то скорее всего функция, в которой эта строка расположилась, является кандидатом на рефакторинг, и лучше его не откладывать. С другой стороны, если у вас много уже готового кода который нужно адаптировать для ядра — clang-format может сильно облегчить вам задачу.

4. Kernel build

Несмотря на то, что процесс описан в других статьях тут и тут, я все же повторюсь.

По шагам процесс сборки ядра довольно прост, если не вдаваться в детали. Для начала ставим необходимые пакеты (использовался Debian 10):

Это без компилятора и обычного для С/С++ разработчика набора программ.
Запускаем конфигурацию:

Тут есть интересный аспект: в качестве шаблона будет браться config ядра от вашего боевого ядра, которое, скорее всего, подготовлено дистрибьютером. Для Debian 10 сборка проходит успешно, если в конфиге потереть информацию о встраиваемых в ядро сертификатах.

Перед попыткой собрать проверьте, что нужные программы уже установлены. Список тут. Чтобы собрать само ядро:

Этого достаточно для проверки собираемости, но недостаточно для запуска ядра в системе, так как без модулей ядро на реальной системе практически беспомощно.

Если какой-то модуль не собирается, просто вырубите его в ближайшем Makefile-е (если 100% уверены, что не пытались в нём что-то улучшить). Наверняка он вам не пригодится, и тратить время на исправления смысла нет.

Теперь можно деплоить то, что получилось, на эту же систему.

Хотя, конечно, экспериментировать с ядром на той же машине, где ведётся разработка — дело рискованное.

Поэтому как минимум нужно снять снапшот, сделать резервную копию или лучше вообще выполнять отладку на другой (лучше виртуальной) машине. Но как это делать, я пока не разбирался. Если у кого есть такой опыт — пишите в комменты, добавлю в статью.

На моей системе загрузчик после установки ядра автоматически обновился. Если у вас этого не произошло, то это делается это на Debian-подобных системах командой:

Update: Как верно заметил gavk, ядро давно уже умеет собирать пакеты, причём как для deb, так и для rpm.
Команда

выводит весь ассортимент. Так что команда

должна собрать пакет с ядром.

5. Patches

Вот теперь мы действительно подготовили код для отправки. Лучше всего, чтобы это был единственный коммит. Так проще делать ревью и так быстрее вам ответят. Всё проверив, наконец-то делаем коммит.

Ещё можно комментарии к коммиту дополнить в человеческом текстовом редакторе.

И теперь его можно оформить в виде того самого письма. Правила хорошего тона, или best practice, если угодно — это 75 символов на строку.

В результате получите два файла. В первом 000-cover-letter.patch нужно указать заголовок письма "Subject" и основное описание патча. В описании патча пишем, для чего он создавался, кому он сделает жизнь на нашей планете лучше и каким образом. Только не словоблудим про космические корабли в Большом театре, а пишем лаконично и по делу. И не в коем случае не пишите корпоративную лабуду а-ля "Без этого патча мой бизнес встанет, меня уволят, а дети мои умрут от голода". Нет, строго по существу: "Увидел вот такую проблему вот тут, починить решил вот таким образом, исходники патча прилагаю". Всё, вы восхитительны! А если не превысили 75 символов на строку, то восхитительны в квадрате.

А ещё один волшебный скриптик ./scripts/getmaintainers.pl <patch file> позволит узнать, кому письмо отправлять.

И вот он, момент отправления письма, ради которого всё и затевалось:

После того, как ваш патч был принят, крайне желательно удалить свою ветку.

6. Debuging

И чуть-чуть про отладку. Бонус "на сладкое" для начинающих разработчиков ядра, так сказать.

Как правило, при ошибке вы получаете лог с calltrace-ом. Там указываются имена функций и смещения. Примерно вот так:

Так вот, чтобы понять, в каком месте функции произошла ошибка, достаточно запустить дебагер с подгруженным в него модулем:

Важно, чтобы в модуле сохранились символы (stripped модуль вам тут не поможет).

Выполнив команду list

вы увидите строку кода, приведшую к ошибке. В случае передачи управления по неверному адресу, вы увидите следующую за ошибкой строку.

Зачем вообще самому компилировать ядро?
Пожалуй, главный вопрос, который задают по поводу компиляции ядра: "А зачем мне это делать?".
Многие считают это бессмысленной тратой времени для того, чтобы показать себя умным и продвинутым "линуксоидом". На самом деле компиляция ядра - это очень важное дело. Допустим, вы купили новый ноутбук, в котором у вас не работает веб-камера. Ваши действия? Вы заглядываете в поисковик и ищите решение проблемы по этому вопросу. Довольно часто может оказаться, что ваша веб-камера работает на ядре более новой версии, чем у вас. Если вы не знаете, какая у вас версия - введите в терминале uname -r , в результате вы получите версию ядра (например, linux-2.6.31-10). Также компиляция ядра широко применяется для увеличения производительности: дело в том, что по умолчанию в дистрибутивах ядра компилируются "для всех", из-за этого в нем включено огромное количество драйверов, которые вам могут не понадобиться. Так что если вы хорошо знаете используемое оборудование, то можете отключить ненужные драйвера на этапе конфигурирования. Также есть возможность включить поддержку более 4х Гигабайт оперативной памяти, не меняя разрядность системы. Итак, если вам всё же необходимо иметь своё ядро, приступим к компиляции!

Распаковка архива исходного кода.
После того как вы получили архив с исходным кодом, вам необходимо распаковать архив в папку. Это можно сделать из графических файловых менеджеров (dolphin,nautilus и т.п) или через mc. Либо воспользуйтесь традиционной командой tar:
tar -zxvf путь_до_архива
Теперь у вас есть папка и исходным кодом, перейдите в неё, используя команду cd каталог_исходного_кода_ядра (чтобы просмотреть список каталогов в папке, используйте команду ls ).

Конфигурация ядра.
После того как вы перешли в каталог с исходным кодом ядра, необходимо выполнить "20 минутную" конфигурацию ядра. Цель её - оставить только нужные драйвера и функции. Все команды уже нужно исполнять от имени суперпользователя.

make config - консольный режим конфигуратора.


make menuconfig - консольный режим в виде списка.


make xconfig - графический режим.


После внесения нужных изменений, сохраните настройки и выйдите из конфигуратора.

Компиляция.
Пришло время завершающего этапа сборки - компиляция. Это делается двумя командами:
make && make install
Первая команда скомпилирует в машинный код все файлы, а вторая установит новое ядро в вашу систему.
Ждем от 20 минут до нескольких часов (в зависимости от мощности компьютера). Ядро установлено. Чтобы оно появилось в списке grub(2), введите (от суперпользователя)
update-grub
Теперь после перезагрузки нажмите "Escape", и вы увидите новое ядро в списке. Если же ядро не включается, то просто загрузитесь со старым ядром и конфигурируйте более аккуратно.

KernelCheck - компиляция ядра не заходя в консоль.
KernelCheck позволяет собрать ядро в полностью графическом режиме для Debian и основанных на нём дистрибутивов. После запуска, KernelCheck предложит свежие версии ядра и патчи, и после вашего согласия, скачает исходных код, запустит графический конфигуратор. Программа соберет ядро в .deb пакеты и установит их. Вам останется лишь перезагрузиться.

Автор: Ололошник, дата: 31 марта 2010 , время: 17:19:02 (MSK).
Всё так и делайте если не получится снова делайте пока не отключат электричество Автор: Subsanek, дата: 31 марта 2010 , время: 17:41:34 (MSK).
Компилят в основном ночью, а электричество ночью дешевле.

Автор: Soft, дата: 31 марта 2010 , время: 20:46:09 (MSK).
Если блог для новичков, то сразу бы с кернелчек программы начать надо, а потом уже для тех кому не страшно самому))))

Читайте также: