Сборка ядра: Debian Way

Алексей Федорчук
23 марта 2006 г

Ядро — это почти такая же программа, как и любая другая. И в этом качестве также поддается управлению дистрибутивными средствами пакетного менеджмента.

В репозитории Ubuntu достаточно регулярно появляются бинарные пакеты прекомпилированных образов — так что при необходимости смены его версии (а необходимость такая возникает при появлении в ядре поддержки позарез нужной функции), достаточно установить его обычным образом:

$ apt-get install linux-image-2.6.XX-##-arch

Где XX — номер версии ядра (например, 2.6.15), ## — номер сборки пакета образа, а arch — архитектура, под которую этот образ сокмпилирован (например, 386 и 686 — под абстрактные процессоры Intel вообще и под Pentium Pro и выше, соответственно, k7 и amd64 — под обычный Atlhon и под Athlon 64-битный).

Установленное таким образом ядро будет поддерживать те его функции, которые показались необходимыми майнтайнерам. А как быть, если возникнет необходимость в ядре, сконфигурированном собственноручно? Конечно, времена, когда первым делом линуксоида после установки системы было — пересборка ядра, давно прошли. Нынче, по крайней мере в большинстве пакетных дистрибутивов, хорошим тоном считается пользовать прекомпилированное ядро, собранное майнтайнером (или одно из предоставляемых им ядер). И, надо признать, к тому есть немало оснований: в поставляемых с дистрибутивами, рассчитанными на широкие массы трудящихся, ядрах задействована модульная поддержка всех распространённых устройств, таких, как контроллеры жёстких дисков SATA и ATA-RAID. А штатный способ загрузки их ныне — через специально сконфигурированный образ виртуального загрузочного диска initrd, — обеспечивает работу системы даже в том случае, если в качестве модулей поддерживаются загрузочные устройства и устройства, несущие корневую файловую систему.

Тем не менее, необходимость в перекомпиляции ядра иногда возникает. И причин к ней — две. Во-первых, модульная поддержка широкого круга устройств и загрузка системы через initrd, неизбежные для ядер инсталляционных дисков (действительно, не будешь же жёстко встраивать в ядро поддержку всех возможных типов ATA- и SCSI-контроллеров или бесчисленных сетевых карт), далеко не идеальна для индивидуальной пользовательской машины. А во-вторых, модульная поддержка не всегда обеспечивает оптимальную работу устройств, в частности — максимальную производительность тех же жёстких дисков.

В документации к Ubuntu и Kubuntu указаний по части сборки ядра, пожалуй, не найти. Однако тут впору опять вспомнить, что это — дети обширного Debian-семейства, и обратиться к документации по этому дистрибутиву. Каковая предлагает два метода выполнения этой процедуры — «как всегда» и «как лучше». На первом останавливаться не буду — он многократно описывался во всех книгах по Linux и бесчисленных Сетевых источниках. Скажу только, что он обычно сводится (при наличии исходников ядра, разумеется) к выполнению команды make menuconfigure, включению нужных и отключению ненужных опций через меню этой программы (каких именно — разговор совершенно особый, который мог бы составить предмет отдельной книги), собственно компиляции образа ядра и его модулей командами типа make и make modules, и установке получившихся бинарников в должные ветви файлового древа (как и куда — опять-таки, возможны варианты, на которых задерживаться не буду). В общем, любой линуксоид нашего поколения знает, как собирать ядро традиционным способом — не хуже, чем любой советский ребенок знал, как очищается политура, а наичнающим пользователям знать детали необходимости нет.

А вот метод «как нужно» — Debain-специфический, и избавляет пользователя от ряда деталей, копаться в которых ему совсем не обязательно. Он предусматривает для пересборки ядра специальный пакет — kernel-package, каковой и надлежит установить с помощью зазубренных ранее волшебных заклинаний:

S apt-get install kernel-package

Заодно следует обзавестись и сопутствующими пакетами — debhelper, modutils и libncurses5-dev (последний нужен для генерации меню по команде make menuconfig). И еще — пакетом fakeroot, который отвечает за запуск команд в имитируемом root-окружении.

Далее, естественно, требуются исходники ядра. В качестве таковых можно взять последнюю версию ядра канонического, сkernel.org, можно — дополнить их патчами других разработчиков. А можно — просто пересобрать штатное ядро дистрибутива. В последнем случае нужно установить соответствующий пакет с исходниками, например:

S sudo apt-get install kernel-source-2.6.XX

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

И еще: почти все последующие процедуры потребуют привилегий администратора, так что, дабы не прибегать к sudo перед каждой, их можно получить на все время «ядерных» упражнений — напоминаю, как:

$ sudo -s -H

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

S tar xjvf kernel-source-2.6.XX.tar.bz2

Да, в промежутке можно отредактировать файл /etc/kernel-pkg.conf — правда, кроме собственного имени и электронного адреса, вписывать в него вроде нечего. Следующий этап Debian-метода построения ядра выполняется, «как всегда». То есть — переходом в соответствующий каталог

S cd /usr/src/linux-source-2.6.12/

копированием в него нашего рабочего конфига ядра:

S cp /boot/config-2.6.12-1-amd64-generic .config

(дабы не начинать конфигурирование с нуля, а лишь вносить необходимые коррективы) и запуском команды

S make menuconfig

Процедуру конфигурирования описывать не буду — в контексте нынешней темы скажу только, что, в целях избавления от initrd, необходимо жёстко встроить в ядро поддержку всего, имеющего отношение к старту системы. То есть — контроллера «несущего» систему диска и типа файловой системы, содержащей корень файлового древа. Неплохо также избавиться от поддержки «лишних» чипсетов и прочего не имеющего быть оборудования.

Далее руководство в приказном порядке рекомендует выполнить очистку дерева исходников:

$ make-kpkg clean

что требуется для уничтожения следов от номеров предыдущих ревизий ядра — следующей командой мы определим свою их нумерацию. А командой этой будет

$ fakeroot make-kpkg --append_to_version
     -amd64 --revision=rev.01 kernel_image

Здесь fakeroot создает «правильное» root-окружение (то есть команда может быть запущена от имени пользователя), make-kpkg — собственно программа для построения бинарного «ядерного» пакета, ее опции предписывают добавлять к имени пакета номер версии ядра, архитектуру, под которую оно собиралось, и номер ревизии, то есть нашей собственной сборки, а kernel_image — имя целевого пакета.

В результате указанной директивы сначала происходит компиляция ядра, а потом из него собирается самый обычный deb-пакет вида kernel-image-2.6.12-amd64_rev.01_amd64.deb, помещаемый в каталог /usr/src. Так что дело остается за малым — установить его обычным же образом:

$ cd ..
$ dpkg -i kernel-image-2.6.12-amd64_rev.01_amd64.deb

При этом файл образа ядра и соответствующий ему System.map будут не только скопированы куда следует (то есть в каталог /boot — если он составляет отдельную ветвь файлового древа, нужно не забыть предварительно его примонтировать!), но и внесены изменения в файл конфигурации загрузчика (например — в /boot/grub/menu.lst, если таковым выступает GRUB): новое ядро займет умолчальную позицию в его меню, старое же сохранится в качестве резервного.