Product SiteDocumentation Site

8.10. Компиляция Ядра

Включаемые в дистрибутивы Debian ядра содержат в себе максимально количество функциональных возможностей, а также максимум драйверов. В результате этого становится возможным с помощью ядра настроить как максимум аппаратных устройств уже на стадии установки, загрузки и дальнейшей эксплуатации системы. Но некоторые предпочитают перекомпилировать (пересобрать) ядро, включив только то, что им действительно нужно. Для такого подхода имеются две причины. Первая - возможность оптимизации использования физической памяти (RAM) поскольку код ядра постоянно находится в ней (и никогда не “выгружается”, даже частично, в файл подкачки). Избыточное использование ядром физической памяти (а она недёшева, и её часто не хватает на компьютерах пользователей) может уменьшить общую производительность системы. Вторая причина - локально скомпилированные ядра помогают снизить риск проблем безопасности. За счёт исключения ненужного (только незначительное количество кода ядра будет включено в состав ядра, скомпилировано и в дальнейшем выполняться) в конечном итоге повысится защищённость и производительность системы.
Перекомпиляция ядра необходима также, если вы хотите использовать некоторые особенности, которые доступны только в виде патчей (и не включены в стандартную версию ядра).

8.10.1. Введение и предпосылки

Неудивительно, что Debian управляет ядром в виде пакета, а ядра традиционно не компилируются и не устанавливаются. Поскольку ядро остается под контролем системы упаковки, его можно затем полностью удалить или развернуть на нескольких машинах. Кроме того, сценарии, связанные с этими пакетами, автоматизируют процесс подключения устанавливаемого ядра в загрузчик и генерацию образа initrd для загрузки.
Исходники исходного кода Linux содержат всё необходимое для сборки пакета ядра Debian. Но вам всё равно необходимо установить build-essential, чтобы убедиться, что у вас есть инструменты, необходимые для сборки пакета Debian. Кроме того, этап настройки ядра требует пакет libncurses-dev (ранее libncurses5-dev который теперь является переходным пакетом). Наконец, пакет fakeroot позволит создать пакет Debian без использования прав администратора.

8.10.2. Получение исходного кода

Как и всё, что может быть полезно в системе Debian, исходные коды ядра Linux доступны в пакете. Чтобы получить их, просто установите пакет linux-source-version (после "тире" дополните нужной вам версией, из числа имеющихся в репозиториях). Команда apt search ^linux-source выполнит поиск по регулярному выражению пакетов Debian с различными версиями ядра. Последняя версия доступна в дистрибутиве Unstable: вы можете получить её без большого риска (особенно, если ваш APT настроен в соответствии с инструкциями в разделе Раздел 6.2.6, «Работа с несколькими дистрибутивами»). Обратите внимание, что исходный код, содержащийся в этих пакетах, не совсем соответствует коду, опубликованному Линусом Торвальдсом и разработчиками ядра; Как и все дистрибутивы, Debian применяет ряд исправлений, которые могут (а могут и не попасть) в основную версию Linux. Эти модификации включают в себя резервный перенос исправлений/функций/драйверов из более новых версий ядра, новые функции, которые ещё (полностью) не объединены с исходным деревом Linux, а иногда даже специфичные для Debian изменения.
Оставшаяся часть этого раздела посвящена версии ядра Linux 5.10, но примеры, конечно, можно адаптировать к конкретной версии ядра, которую вы хотите.
Мы полагаем (для демонстрации примеров), что пакет linux-source-5.10 у вас установлен. В составе пакета имеется архив /usr/src/linux-source-5.10.tar.xz, в котором в сжатом виде хранятся коды ядра. Вы должны извлечь эти файлы в новый каталог (но не напрямую в каталог /usr/src/, а в тот каталог, где нет особых требований к правам доступа для компиляции Linux ядра): целесообразно назвать его ~/kernel/.
$ mkdir ~/kernel; cd ~/kernel
$ tar -xaf /usr/src/linux-source-5.10.tar.xz
Чтобы собрать ядро из чистых исходных кодов, просто загрузите tar-архив выбранной вами версии с сайта kernel.org, проверьте целостность после импорта ключа сопровождающего ядра, а затем действуйте, как описано в следующих главах.

$ wget https://kernel.org/pub/linux/kernel/v5.x/linux-5.10.62.tar.xz
[..]
$ wget https://kernel.org/pub/linux/kernel/v5.x/linux-5.10.62.tar.sign
[..]
$ unxz -c linux-5.10.62.tar.xz | gpg --verify linux-5.10.62.tar.sign -
gpg: Signature made Fri 03 Sep 2021 10:11:35 AM CEST
gpg:                using RSA key 647F28654894E3BD457199BE38DBBDC86092693E
gpg: Good signature from "Greg Kroah-Hartman <gregkh@linuxfoundation.org>" [unknown]
gpg:                 aka "Greg Kroah-Hartman (Linux kernel stable release signing key) <greg@kroah.com>" [unknown]
gpg:                 aka "Greg Kroah-Hartman <gregkh@kernel.org>" [unknown]
gpg: WARNING: This key is not certified with a trusted signature!
gpg:          There is no indication that the signature belongs to the owner.
Primary key fingerprint: 647F 2865 4894 E3BD 4571  99BE 38DB BDC8 6092 693E

8.10.3. Конфигурирование ядра

Следующий шаг заключается в настройке ядра в соответствии с вашими потребностями. Более точный алгоритм работы зависит от ваших целей.
При перекомпиляции более современной версии ядра (возможно с дополнительными заплатками), конфигурация ядра должна быть как можно ближе к тому, что предлагает Debian. В этом случае, вместо того, чтобы перенастраивать все с нуля, достаточно скопировать /boot/config-version (узнать версию ядра, работающего сейчас на вашем компьютере, можно командой uname -r) в новый файл с именем .config, разместив его в каталог, содержащий исходные коды ядра. В этом случае обязательно прочтите врезку СОВЕТ Отсутствие debian/certs/debian-uefi-certs.pem.
$ cp /boot/config-5.10.0-8-amd64 ~/kernel/linux-source-5.10/.config
Если вам не нужно изменять конфигурацию ядра, вы можете остановиться здесь и пропустить раздел Раздел 8.10.4, «Компиляция и Сборка Пакета». В противном случае, если необходимо внести изменения в конфигурацию ядра или вы решили сами всё настроить с нуля, то необходимо выделить достаточно времени на эту работу. В каталоге с исходными кодами ядра присутствуют и различные специальные интерфейсы, которые могут быть использованы посредством вызова команды make target, где в качестве target выступает одно из значений, описанных ниже.
make menuconfig компилирует и выполняет в псевдографическом интерфейсе (для этого необходимо установить пакет libncurses-dev). В программе можно передвигаться и выбирать опции в иерархической структуре. Нажатие клавиши Space изменение значения выбираемой опции, а нажатие Enter вход внутрь выбранной опции; кнопка интерфейса Select возвращает на выбранное подменю; Exit закрывает настоящий экран и сдвигает позицию курсора назад по иерархии; Help отобразит более детальную информацию о роли выбранной опции. Клавиши со стрелками позволяют передвигаться в списке опций и кнопок. Для выхода из программы выберите Exit из главного меню. В этот момент программа предложит сохранить сделанные изменения - если вы удовлетворены сделанными изменениями, то сохраните их.
Другие интерфейсы имеют похожие функциональные возможности, но они работают в более современных графических оболочках; такие как make xconfig, которая использует графический интерфейс Qt, и make gconfig, использующий GTK+. Первый нуждается в пакете qtbase5-dev, в то время как второй зависит от наличия пакетов libglade2-dev и libgtk2.0-dev.
При использовании одного из этих интерфейсов конфигурации всегда полезно начинать с разумной конфигурации по умолчанию. Ядро предоставляет такие конфигурации в arch/arch/configs/*_defconfig. Вы можете взять выбранную вами оттуда конфигурацию поместив её в новое место командой вроде make x86_64_defconfig (в случае 64-битного ПК) или make i386_defconfig (в случае 32-битного ПК). Программа скопирует .config из заготовленных разработчиками оптимальных конфигураций в каталог компиляции ядра.

8.10.4. Компиляция и Сборка Пакета

Как только конфигурация ядра будет готова, можно выполнить команду make deb-pkg, которая сгенерирует до 5 пакетов Debian:
linux-image-version
содержит образ ядра и связанные модули,
linux-headers-version
содержит заголовочные файлы, необходимые для сборки внешних модулей,
linux-firmware-image-version
содержит файлы прошивки, необходимые некоторым драйверам (этот пакет может отсутствовать при сборке из исходных кодов ядра, предоставленных Debian),
linux-image-version-dbg
содержит символы отладки для образа ядра и его модулей (создаются только в том случае, еслиCONFIG_DEBUG_INFO=y), и
linux-libc-dev
содержит заголовочные файлы, относящиеся к некоторым библиотекам пользовательского пространства, таким как GNU glibc.
Суффикс, добавляемый в конце к названию ядра, version определяется путем объединения исходной версии (как определено переменными VERSION, PATCHLEVEL, SUBLEVEL и EXTRAVERSION в Makefile), LOCALVERSION конфигурационного параметра и переменной окружения LOCALVERSION. Версия пакета повторно использует одну и ту же строку версии с добавленной ревизией, которая регулярно увеличивается (и сохраняется в .version), за исключением случаев, когда вы переопределите его с помощью переменной окруженияKDEB_PKGVERSION.
$ make deb-pkg LOCALVERSION=-falcot KDEB_PKGVERSION=$(make kernelversion)-1
[...]
$ ls ../*.deb
../linux-headers-5.10.46-falcot_5.10.46-1_amd64.deb
../linux-image-5.10.46-falcot_5.10.46-1_amd64.deb
../linux-image-5.10.46-falcot-dbg_5.10.46-1_amd64.deb
../linux-libc-dev_5.10.46-1_amd64.deb
Весь процесс требует около 20 ГБ свободного места, не менее 8 ГБ ОЗУ и несколько часов компиляции (с использованием одного ядра) для стандартного ядра Debian amd64. Эти требования можно значительно снизить, отключив отладочную информацию с помощью CONFIG_DEBUG_INFO=n, но это сделает невозможным отслеживание ошибок ядра («oops») с помощью команды gdb, а также остановит создание пакета linux-image-version-dbg.

8.10.5. Компиляция Внешних Модулей (динамически загружаемые модули ядра)

Некоторые модули, не включённые в официальный проект ядра Linux, поддерживаются за его пределами. Чтобы была возможность их использовать, они должны быть скомпилированы рядом с соответствующим ядром. Определённое количество таких модулей поддерживается Debian путём включения их в специальные пакеты, такие как vpb-driver-source (дополнительные модули для аппаратной Voicetronix телефонии) или leds-alix-source (драйвер PCEngines ALIX 2/3 плат).
Эти пакеты многочисленны и разнообразны, команда apt-cache rdepends module-assistant$ может показать список, предоставленный Debian. Однако полный список не особенно полезен, поскольку нет особой причины для компиляции внешних модулей, за исключением тех случаев, когда вы знаете, что они вам нужны. В таких случаях в документации устройства обычно подробно описывается конкретный модуль(-и), который необходим для работы под Linux.
Для примера, давайте рассмотрим пакет xtables-addons-source: после его установки появится архив исходного кода модуля .tar.bz2, располагающийся в каталоге /usr/src/. Далее можно было бы вручную извлечь данные из архива и построить модуль, но на практике предпочтительным способом является использование DKMS (инфраструктура для поддержки динамически загружаемых модулей ядра). Пакеты, название которых оканчивается на суффикс -dkms, предлагаются для большинства модулей, которым необходима интеграция с ядром через DKMS. В приведённом примере, установка пакета xtables-addons-dkms добавит всё необходимое, что нужно для компиляции внешнего модуля для настоящего ядра. Обратите только внимание, чтобы был установлен и пакет linux-headers-*, соответствующий версии ядра. Например, если вы используете linux-image-amd64, то вам необходимо доустановить и пакет linux-headers-amd64.
$ sudo apt install dahdi-dkms
[...]
Setting up dkms (2.8.4-3) ...
Setting up linux-headers-5.10.0-8-amd64 (5.10.46-4) ...
/etc/kernel/header_postinst.d/dkms:
dkms: running auto installation service for kernel 5.10.0-8-amd64:.
Setting up dahdi-dkms (1:2.11.1.0.20170917~dfsg-7.4) ...
Loading new dahdi-2.11.1.0.20170917~dfsg-7.4 DKMS files...
Building for 5.10.0-8-amd64
Building initial module for 5.10.0-8-amd64
Done.

dahdi_dummy.ko:
Running module version sanity check.
 - Original module
   - No original module exists within this kernel
 - Installation
   - Installing to /lib/modules/5.10.0-8-amd64/updates/dkms/

dahdi_dynamic_eth.ko:
Running module version sanity check.
 - Original module
   - No original module exists within this kernel
 - Installation
   - Installing to /lib/modules/5.10.0-8-amd64/updates/dkms/

[...]
DKMS: install completed.
$ sudo dkms status
dahdi, 2.11.1.0.20170917~dfsg-7.4, 5.10.0-8-amd64, x86_64: installed
$ sudo modinfo dahdi_dummy
filename:       /lib/modules/5.10.0-8-amd64/updates/dkms/dahdi_dummy.ko
license:        GPL v2
author:         Robert Pleh <robert.pleh@hermes.si>
description:    Timing-Only Driver
depends:        dahdi
retpoline:      Y
name:           dahdi_dummy
vermagic:       5.10.0-8-amd64 SMP mod_unload modversions 
parm:           debug:int

8.10.6. Наложение патча на ядро

Некоторые особенности не включены в стандартное ядро из-за недостатка завершённости кода или некоторых разногласий с сопровождающими ядро. Они могут быть включены в отдельные патчи и распространяться в таком виде (разработчиками патча). В дальнейшем кто угодно может установить такой патч на исходные коды ядра.
Debian иногда предоставляет некоторые из этих патчей в пакетах linux-patch-*, но они часто не попадают в стабильные выпуски ядра (иногда по тем же причинам, по которым они не объединены в официальные исходные выпуски). Эти пакеты устанавливают файлы в каталог /usr/src/kernel-patches/.
Чтобы применить один или несколько из этих установленных патчей, используйте команду patch в каталоге источников, а затем запустите компиляцию ядра, как описано выше. Ниже показан старый пример linux-patch-grsecurity2 и linux-source-4.9.
$ cd ~/kernel/linux-source-4.9
$ make clean
$ zcat /usr/src/kernel-patches/diffs/grsecurity2/grsecurity-3.1-4.9.11-201702181444.patch.gz | patch -p1
Обратите внимание, что устанавливаемый патч не обязательно будет совместим с каждой версией ядра. Может случиться, что команда patch, при попытке наложить патч на исходные коды ядра, потерпит неудачу. Возникшие ошибки будут показаны и даны некоторые подробности, касательно возникшего сбоя. В этом случае, руководствуйтесь документацией, доступной в Debian пакете данного патча (в каталоге /usr/share/doc/linux-patch-*/). В большинстве случаев, сопровождающие патчей указывают, для каких версий ядра они предназначены.