Product SiteDocumentation Site

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

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

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

Unsurprisingly, Debian manages the kernel in the form of a package, which is not how kernels have traditionally been compiled and installed. Since the kernel remains under the control of the packaging system, it can then be removed cleanly, or deployed on several machines. Furthermore, the scripts associated with these packages automate the interaction with the bootloader and the initrd generator.
The upstream Linux sources contain everything needed to build a Debian package of the kernel. But you still need to install build-essential to ensure that you have the tools required to build a Debian package. Furthermore, the configuration step for the kernel requires the libncurses-dev package (formerly libncurses5-dev, which is now a transitional package). Finally, the fakeroot package will enable creation of the Debian package without using administrator's rights.

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

Like anything that can be useful on a Debian system, the Linux kernel sources are available in a package. To retrieve them, just install the linux-source-version package. The apt search ^linux-source command lists the various kernel versions packaged by Debian. The latest version is available in the Unstable distribution: you can retrieve them without much risk (especially if your APT is configured according to the instructions of Раздел 6.2.6, «Работа с отдельными дистрибутивами»). Note that the source code contained in these packages does not correspond precisely with that published by Linus Torvalds and the kernel developers; like all distributions, Debian applies a number of patches, which might (or might not) find their way into the upstream version of Linux. These modifications include backports of fixes/features/drivers from newer kernel versions, new features not yet (entirely) merged in the upstream Linux tree, and sometimes even Debian specific changes.
The remainder of this section focuses on the 5.10 version of the Linux kernel, but the examples can, of course, be adapted to the particular version of the kernel that you want.
We assume the linux-source-5.10 package has been installed. It contains /usr/src/linux-source-6.1.tar.xz, a compressed archive of the kernel sources. You must extract these files in a new directory (not directly under /usr/src/, since there is no need for special permissions to compile a Linux kernel): ~/kernel/ is appropriate.
$ mkdir ~/kernel; cd ~/kernel
$ tar -xaf /usr/src/linux-source-6.1.tar.xz
To build a kernel from the pristine sources, just download the tarball of the version of your choice from kernel.org, verify the integrity after importing the kernel maintainers key, and then proceed as described in the following chapters.

$ wget https://kernel.org/pub/linux/kernel/v6.x/linux-6.1.99.tar.xz
[..]
$ wget https://kernel.org/pub/linux/kernel/v6.x/linux-6.1.99.tar.sign
[..]
$ unxz -c linux-6.1.99.tar.xz | gpg --verify linux-6.1.99.tar.sign -
gpg: Signature made Mon 15 Jul 2024 03:24:49 AM EDT
gpg:                using RSA key 647F28654894E3BD457199BE38DBBDC86092693E
gpg: Good signature from "Greg Kroah-Hartman <gregkh@linuxfoundation.org>" [unknown]
gpg:                 aka "Greg Kroah-Hartman <gregkh@kernel.org>" [unknown]
gpg:                 aka "Greg Kroah-Hartman (Linux kernel stable release signing key) <greg@kroah.com>" [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. Настройка ядра

Следующий шаг содержит настройку ядра в соответствии с вашими потребностями. Более точный алгоритм работы зависит от ваших целей.
When recompiling a more recent version of the kernel (possibly with an additional patch), the configuration will most likely be kept as close as possible to that proposed by Debian. In this case, and rather than reconfiguring everything from scratch, it is sufficient to copy the /boot/config-version file (the version is that of the kernel currently used, which can be found with the uname -r command) into a .config file in the directory containing the kernel sources. Make sure to read sidebar TIP Missing debian/certs/debian-uefi-certs.pem in this case.
$ cp /boot/config-6.1.0-21-amd64 ~/kernel/linux-source-6.1/.config
Если вам не нужно изменять конфигурацию ядра, вы можете остановиться здесь и пропустить раздел Раздел 8.10.4, «Компиляция и Сборка Пакета». В противном случае, если необходимо внести изменения в конфигурацию ядра или вы решили сами всё настроить с нуля, то необходимо выделить достаточно время на эту работу. В каталоге с исходными кодами ядра присутствуют и различные специальные интерфейсы, которые могут быть использованы посредством вызова команды make target, где в качестве target выступает одно из значений, описанных ниже.
make menuconfig compiles and executes a text-mode interface (this is where the libncurses-dev package is required) which allows navigating the options available in a hierarchical structure. Pressing the Space key changes the value of the selected option, and Enter validates the button selected at the bottom of the screen; Select returns to the selected sub-menu; Exit closes the current screen and moves back up in the hierarchy; Help will display more detailed information on the role of the selected option. The arrow keys allow moving within the list of options and buttons. To exit the configuration program, choose Exit from the main menu. The program then offers to save the changes you've made; accept if you are satisfied with your choices.
Other interfaces have similar features, but they work within more modern graphical interfaces; such as make xconfig which uses a Qt graphical interface, and make gconfig which uses GTK+. The former requires qtbase5-dev, while the latter depends on libglade2-dev and libgtk2.0-dev.
Хорошей идеей было бы использовать совместно с теми интерфейсами одну из конфигураций по умолчанию, имеющиеся в комплекте с исходным кодом ядра. Они спроектированы оптимальным образом и расположены в arch/arch/configs/*_defconfig. Вы можете взять выбранную вами оттуда конфигурацию поместив её в новое место командой похожей на make x86_64_defconfig (в случае 64-битного ПК) или make i386_defconfig (в случае 32-разрядный ПК). Программа возьмёт .config из заготовленных разработчиками оптимальных конфигураций и сохраняет его в каталог, где будет компилироваться ядро, то есть по сути копирует этот файл.

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

Once the kernel configuration is ready, a simple make deb-pkg will generate up to 5 Debian packages:
linux-image-version
contains the kernel image and the associated modules,
linux-headers-version
contains the header files required to build external modules,
linux-firmware-image-version
contains the firmware files needed by some drivers (this package might be missing when you build from the kernel sources provided by Debian),
linux-image-version-dbg
contains the debugging symbols for the kernel image and its modules (only created if CONFIG_DEBUG_INFO=y), and
linux-libc-dev
contains headers relevant to some user-space libraries like GNU glibc.
The version is defined by the concatenation of the upstream version (as defined by the variables VERSION, PATCHLEVEL, SUBLEVEL, and EXTRAVERSION in the Makefile), of the LOCALVERSION configuration parameter, and of the LOCALVERSION environment variable. The package version reuses the same version string with an appended revision that is regularly incremented (and stored in .version), except if you override it with the KDEB_PKGVERSION environment variable.
$ 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
The whole process requires around 20 GB of free space, at least 8 GB of RAM, and several hours of compilation (utilizing one core) for a standard amd64 Debian kernel. These requirements can be drastically reduced by disabling the debug information using CONFIG_DEBUG_INFO=n, but this will make it impossible to trace kernel errors (“oops”) using gdb and also stop the creation of the linux-image-version-dbg package.

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

Some modules are maintained outside of the official Linux kernel. To use them, they must be compiled alongside the matching kernel. A number of common third party modules are provided by Debian in dedicated packages, such as vpb-driver-source (extra modules for Voicetronix telephony hardware) or leds-alix-source (driver of PCEngines ALIX 2/3 boards).
These packages are many and varied, apt-cache rdepends module-assistant$ can show the list provided by Debian. However, a complete list isn't particularly useful since there is no particular reason for compiling external modules except when you know you need it. In such cases, the device's documentation will typically detail the specific module(s) it needs to function under Linux.
For example, let's look at the dahdi-source package: after installation, a .tar.bz2 of the module's sources is stored in /usr/src/. While we could manually extract the tarball and build the module, in practice we prefer to automate all this using the DKMS framework (Dynamic Kernel Module Support). Most modules offer the required DKMS integration in a package ending with a -dkms suffix. In our case, installing dahdi-dkms is all that is needed to compile the kernel module for the current kernel provided that we have the linux-headers-* package matching the installed kernel. For instance, if you use linux-image-amd64, you would also install linux-headers-amd64.
$ sudo apt install dahdi-dkms
[...]
Setting up dkms (3.0.10-8+deb12u1) ...
Setting up linux-compiler-gcc-12-x86 (6.1.99-1) ...
Setting up fxload (0.0.20081013-2) ...
Setting up linux-headers-6.1.0-23-common (6.1.99-1) ...
Setting up linux-kbuild-6.1 (6.1.99-1) ...
Setting up dahdi-dkms (1:2.11.1.0.20170917~dfsg-8.4) ...
Loading new dahdi-2.11.1.0.20170917 DKMS files...
Building for 6.1.0-23-amd64
Building initial module for 6.1.0-23-amd64
Done.

dahdi_dummy.ko:
Running module version sanity check.
 - Original module
   - No original module exists within this kernel
 - Installation
   - Installing to /lib/modules/6.1.0-23-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/6.1.0-23-amd64/updates/dkms/

[..]
depmod...
Setting up dahdi-linux (1:2.11.1.0.20170917~dfsg-8.4) ...
Setting up linux-headers-6.1.0-23-amd64 (6.1.99-1) ...
/etc/kernel/header_postinst.d/dkms:
dkms: running auto installation service for kernel 6.1.0-23-amd64.
dkms: autoinstall for kernel: 6.1.0-23-amd64.
Setting up linux-headers-amd64 (6.1.99-1) ...
Processing triggers for man-db (2.11.2-2) ...

$ sudo dkms status
dahdi/2.11.1.0.20170917, 6.1.0-23-amd64, x86_64: installed
$ sudo modinfo dahdi_dummy
 filename:       /lib/modules/6.1.0-23-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:       6.1.0-23-amd64 SMP preempt mod_unload modversions 
sig_id:         PKCS#7
signer:         DKMS module signing key
sig_key:        69:A6:CA:D5:86:6A:FE:F4:A8:04:6A:31:8B:AB:E1:07:88:BA:45:C7
sig_hashalgo:   sha256
signature:      9B:F9:8E:38:4D:06:A6:20:52:33:D9:AE:9D:B9:83:17:BB:5A:18:F1:
		F2:5B:F3:12:06:0A:1D:48:C3:BA:89:2C:40:64:1C:2C:52:7C:46:BE:
		27:49:F5:55:42:1B:71:38:A2:1B:FA:58:BB:CE:7C:70:2C:EC:37:7B:
		65:91:A1:E7:23:6E:B6:92:9D:B9:20:43:F5:39:7F:95:CA:36:DC:C0:
		DA:82:49:AC:21:69:65:DF:5D:0F:C5:8F:E5:E6:92:76:F1:DD:18:7E:
		91:D2:DC:43:86:CA:5B:66:7C:FF:AE:EA:F9:06:F8:55:4A:1F:C0:56:
		8B:F7:6C:9E:77:35:9B:E0:14:9D:C4:68:D8:5E:FD:3F:53:73:F1:B6:
		12:67:9E:F4:68:48:C8:A7:80:69:42:01:83:52:D8:EF:54:FE:11:E4:
		63:3C:6F:B3:B6:BF:E9:4F:DF:52:C4:A7:6B:35:D6:3B:C9:E2:FD:48:
		70:41:D1:D1:68:4C:D4:12:7F:CB:7D:92:E5:E6:79:4A:5B:5E:7C:38:
		1D:98:B2:EF:0E:F3:8D:07:1B:51:75:2A:58:2E:F2:53:BA:6A:79:F5:
		AD:D1:12:08:E1:15:EC:5C:7A:CF:99:A2:9B:DB:BB:C0:EE:BD:C0:96:
		77:92:D7:CC:68:14:A2:61:E0:F2:65:64:54:70:B8:73
parm:           debug:int

8.10.6. Установка Заплатки на Ядро

Некоторые особенности не включены в стандартное ядро из-за недостатка завершённости кода или некоторых разногласий с сопровождающими ядро. Они могут быть включены в отдельные заплатки и распространяться в таком виде (разработчиками заплатки). В дальнейшем кто угодно может установить такую заплатку на исходные коды ядра.
Debian sometimes provides some of these patches in linux-patch-* packages, but they often don't make it into stable releases (sometimes for the very same reasons that they are not merged into the official upstream kernel). These packages install files in the /usr/src/kernel-patches/ directory.
To apply one or more of these installed patches, use the patch command in the sources directory then start compilation of the kernel as described above. The following shows an old example using linux-patch-grsecurity2 and 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-*/). В большинстве случаев, сопровождающие заплаток указывают, для каких версий ядра они предназначены.