Включаемые в дистрибутивы 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
, проверьте целостность после импорта ключа сопровождающего ядра, а затем действуйте, как описано в следующих главах.
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-*/
). В большинстве случаев, сопровождающие патчей указывают, для каких версий ядра они предназначены.