Kernelnotes

Материал из ALT Linux Wiki
Версия от 23:02, 17 ноября 2014; MichaelShigorin (обсуждение | вклад) (+Kernel/build for dummies в качестве более подходящего примера)
Freesource-logo.png Blue Glass Arrow.svg MediaWiki logo.png
Эта страница была перемещена с freesource.info.
Эта страница наверняка требует чистки и улучшения — смело правьте разметку и ссылки.
Просьба по окончанию убрать этот шаблон со страницы.
48px-Mail-mark-junk red.svg.png
Эта статья протухла.
Её нужно существенно доработать или удалить


Внимание!

Использование своего ядра с дистрибутивами ALT Linux не поддерживается как техподдержкой ООО «Альт Линукс», так и силами сообщества. Созданные в багтрекере ошибки, относящиеся к самосборным ядрам, вероятнее всего, будут закрыты как NOTABUG.

Эта страница не описывает, как собирать ядра с kernel.org, но как собирать ядра из репозиториев ALT Linux.

См. тж. Kernel/build for dummies.

Зачем может быть нужно собирать своё ядро?

  • Вы разработчик ядра.
  • Вам нужно ядро, собранное каким-то особым способом (например, со включенной экспериментальной опцией), и ядра в ALT Linux не собраны таким образом.
  • Вы пытаетесь отладить проблему в ядре ALT Linux и в багтракере, списке рассылки или техподдержке вам подсказали, что для этого нужно собрать ядро специальным способом
  • У вас есть устройство, не поддерживаемое ядрами ALT Linux (только изредка! Очень часто достаточно просто собрать свой модуль к ядру, см. ниже).

Почему обычно не нужно собирать своё ядро?

  • Это скучное занятие.
  • Если вам нужен специальный драйвер, то достаточно собрать модуль к уже имеющемуся ядру.
  • Распространённые мифы про сборку ядра ложны:
    • Сборка ядра — простое дело
      Современный PC — достаточно сложное устройство, и правильный выбор опций компиляции — нетривиальное занятие.
      Дистрибутивные ядра оптимизированы под «средний» компьютер, пересборка увеличивает производительность
      Не подтверждается тестами. Чаще наоборот: неправильно собранное ядро замедляет систему.
      Сборка ядра — обязательное дело любого линуксоида
      Без комментариев
      Ненужные драйвера тормозят и занимают память
      Ненужные драйвера лежат на диске в виде модулей и не загружаются в память.
      Ядро с драйверами, вкомпилированными внутрь, работает быстрее
      Не подтверждается тестами. Загрузка модулей занимает несколько секунд при старте компьютера, дальнейшее использование идентично по скорости вкомпилированным драйверам.

Предупреждение

Статья частично протухла. vsu@ советует читать доки в kernel-build-tools.

Собираем новое ядро

Будем для примера собирать ядро версии 2.6.23. Вам понадобится хорошая быстрая машина, с быстрым процессором, и большим объемом ОЗУ[1]. Для ускорения сборки можно использовать ccache, установив для этого переменные:

$ export LC_ALL=C
$ export GCC_USE_CCACHE=1

Подготовительный этап

I

У ALT Linux разработана своя среда (kernel-build-tools) для сборки ядер. Основным мантейнером этой среды является vsu; по состоянию на декабрь 2009 последние правки публиковал aspsk:

$ git clone git://git.altlinux.org/people/vsu/packages/kernel-build-tools
$ cd kernel-build-tools
$ ls
$ git remote add aspsk git://git.altlinux.org/people/aspsk/packages/kernel-build-tools
$ git remote update
$ git branch -r


Как видно, среда состоит из набора скриптов.


II

Репозиторий c ядром должен находиться в директории kernel.

Забираем ядро, например, у vsu или lakostis:

$ git clone git://git.altlinux.org/people/vsu/packages/kernel-image-2.6.18 kernel

или

$ git clone git://git.altlinux.org/people/lakostis/packages/kernel-image-2.6.22 kernel

Добавляем репозиторий, содержащий новую версию ядра (для git-remote может потребоваться поставить пакет perl-GIT):

$ git remote add linux-2.6.23 git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-2.6.23.y.git

В master ветку этого репозитория Линус помещает обновления для ядер серии 2.6.23 (например 2.6.23.1, 2.6.23.2…). В нашем репозитории будет создана ветка linux-2.6.23/master, которая будет отслеживать обновления для ванильного ядра 2.6.23.

Загрузим с репозитория linux-2.6.23 исходный код ядра.

$ git fetch linux-2.6.23

Теперь в нашем репозитории ветка linux-2.6.23/master содержит ядро 2.6.23 с обновлениями. Убедимся:

$ git-log --pretty=short -n 1 linux-2.6.23/master
commit 4367388f04eea72e78347dc9b299698bf4275f92
Author: Greg Kroah-Hartman <gregkh@suse.de>

    Linux 2.6.23.1

Собрираем пакет kernel-source-2.6.23-1.0.0-alt1.noarch.rpm

Как видно, данный пакет не зависит от архитектуры. Внутри пакета содержиться только файл с иходными кодами ванильного ядра: /usr/src/kernel/sources/kernel-source-2.6.23.tar.bz2

Заметьте, что данный пакет содержит исходный код ядра версии 2.6.23, а не 2.6.23.1. Собрать этот пакет не составит труда. Достаточно:

$ git checkout -b kernel-source origin/kernel-source # создадим ветки на основе ветки того, кого мы скопировали
$ git pull -s ours . tag v2.6.23 # иначе будет ругаться gear
$ vim kernel-source.spec # увеличиваем версию
$ add_changelog kernel-source.spec

В ответ на ругань add_changelog что версия пакета не изменилась, можно добавить к alt1 точку: 'alt1.', потом удалить. Версия пакета не изменяется, а изменяется имя пакета.

$ vim .gear/rules  # обновить версию ядра в файле (тег)
$ gear-update-tag -a -c
$ git add .gear/rules kernel-source.spec
$ git commit -m "kernel-source-2.6.23 1.0.0-alt1"

Осталось собрать сам пакет с помощью gear в hasher:

$ gear --hasher -- hsh
или
$ gear --hasher -- hsh --apt-config=$HOME/apt/apt.conf.sisyphus.x86_64.hasher $HOME/hasher

Замечания вида:

warning: Macro %kernel_srcdir not found
warning: Macro %kernel_srcdir not found
warning: Macro %kernel_src not found

на результат не влияют, там BuildRequires(pre) не хватает. После сборки этот пакет будет находится в репозитории hasher-a.

Собираем пакет kernel-image-std-smp-2.6.23-alt1.i586.rpm

Собственно этот пакет содержит само ядро + стандартные модули поставляемые с ядром.

Несколько слов о структуре репозитория. На мой взгляд следует различать ветки:

  • kernel-source — цель этой ветки создать пакет с исходниками ванильного ядра 2.6.23 (мы использовали эту ветку на предыдущем шаге).
  • начинающиеся с feat-*-* fix-*-* . Каждая такая ветка содержит ванильное ядро + какое-то одно исправление, дополнение, патч.

Имя ветки сообщает, какое конкретное дополнение она несет.

  • fix-stable — содержит ванильное ядро с последними исправлениями 2.6.23.1.
  • kernel-image-std-smp — содержит пропатчиное ядро. эту ветку мержутся ветки fix-stable, feat-*-*, fix-*-*, fix-stable

Цель ветки kernel-image-std-smp создать мега патч-бомбу который накладывается на ванильное ядро 2.6.23, скомпилировать бинарное ядро, собрать пакет.

Файл branches-to-merge используется скриптом merge-all-branches. Может возникнуть вопрос: «Зачем мержить ветки которые указаны в branches-to-merge, если они уже в замерженыы в ветку kernel-image-std-smp ?» Ответ: Периодически в этих ветках появляется что-то новое, вот скрипт и проверяет, что появилось. Ещё возможен вариант вида branch-* скрипт merge-all-branches проверяет, есть ли что-то новое, если нет — ничего не делает, если есть — спрашивает, надо ли это мержить.

В моем случае, накатывать 2.6.23 поверх пропатченого 2.6.18, бесмысленно, иначе там всё развалится. Придётся делать по сути rebase всех веток с патчами, и подцеплять к старой истории в самом конце. При сборке 2.6.23 лучше создать новые ветки fix-stable, kernel-image-std-smp, …

A

Cоздадим ветку fix-stable. Задача этой ветки содержать последние официальные исправления для ядра от Linus Torvalds:

$ git checkout -b fix-stable linux-2.6.23/master

При будущих обновлениях можно поступать одним из следующим способов: 1. Из tracking branch:

$ git fetch linux-2.6.23
$ git pull . linux-2.6.23/master

2. Загрузить обновления непосредственно из репозитория Linus-а:

$ git pull git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-2.6.23.y.git

B

Создадим ветку kernel-image-std-smp на основе тега v2.6.23. Задача этой ветки содержать код ядра со всеми приложеными патчами. То есть в эту ветку мержатся остальные ветки feat-*-* fix-*-*.

$git checkout -b kernel-image-std-smp v2.6.23

Заберем из старой ветки vsu/kernel-image-std-smp файлы: kernel-image.spec config-i586 config-x86_64 branches-to-merge .gear/rules modules.build

Для каждого вышеперечисленного файла выполним:

$ git ls-tree vsu/kernel-image-std-smp
$ git cat-file blob 'sha1' >kernel-image.spec
$ git add -f kernel-image.spec config-i586 config-x86_64 branches-to-merge .gear/rules modules.build

флаг -f указывает добавить .gear/rules, даже если он занесен в .gitignore

C

Создадим ветки feat-*-* и fix-*-*. Например создадим ветку добавляющую поддержку файловой системы unioinfs.

$ git checkout -b feat-fs-unionfs v2.6.23

Патч можно наложить в ручную (patch -p1 < .....) или же средствами git. Что будет более правильно, и облегчит добавление файлов в index, если патч затрагивает слишком много файлов:

$ git apply --index --whitespace=nowarn unionfs.patch

Отличие от patch в том, что git apply рассматривает любой fuzz как ошибку. Ещё особенность в том, что по умолчанию, если есть хотя бы одна ошибка, патч не применяется вообще. Можно добавить — -reject, чтобы создавались *.rej, как с обычным patch. Кстати, такой внешний патч может иметь смысл совать в отдельную ветку, растущую прямо из той версии ядра, для которой предназначен патч а потом уже мержить. Дело в том, что 3way merge зачастую работает надёжнее, чем наложение патча на изменившуюся версию изменения из патча иногда могут молча улетать в другой участок с похожим содержимым.

$ git commit -m "Add unionfs 2.1.8 support"

Ничего страшного не будет если самому создать сам ветку git checkout -b fix-xxx, а потом добавить коммит из ветки vsu/fix-xxx с помощью git cherry-pick. vsu так же делал большей части этих веток. То есть получается мы крадем коммиты vsu с помощью cherry-pick. Единственная неприятность от cherry-pick — если эти коммиты появятся в нескольких местах, потом, возможно, придётся что-то мержить руками. Если изменения точно совпадают, git merge происходит автоматически, если с одной стороны есть ещё какие-то изменения сверху, может вылезти конфликт на ровном месте.

Если Linus Torvalds добавил в официальное ядро присутвовавшие у нас исправления то можно сделать в ветке fix-stable:

$ git pull -s ours fix-xxx

этот фиктивный мерж проходит всегда автоматом, а потом git уже просто не смотрит внутрь этой ветки.

В итоге у меня получились следующие ветки :

feat-core- -rt
feat-core-bootsplash
feat-evms
feat-evms-nodm
feat-fs-squashfs
feat-fs-unionfs
fix-core- -init
fix-core- -syslog
fix-stable
kernel-image-std-smp
kernel-source
master

D

Мержим все исправления в ветку kernel-image-std-smp, исправляем конфликты.

$ git pull . feat-fs-unionfs

E

В ветке kernel-image-std-smp, создадим новый конфиг на базе старого:

$ cp config-i586 .config
$ make oldconig

При обработке make oldconfig, следует учитывать тот факт, что при наличии возможности скомпилировать некую часть ядра в виде модуля, следует ее выбрать. Чаще всего модули не компилируются непосредственно в ядро, но бывают исключения.

Проверяем все ли впорядке:

$ make menuconfig

Опцию CONFIG_LOCALVERSION_AUTO следует отключить.

$ cp .config config-i586
$ vim kernel-image.spec .gear/rules
$ add_changelog kernel-image.spec
$ gear-update-tag -acv
$ git add config-i586 kernel-image.spec .gear/rules
$ git commit

F

Собираем ядро

$ ./buildkernel-hsh --hsh-workdir=/home/stanv/hasher std-smp
или
$ ./buildkernel-hsh --hsh-options=--apt-config=/home/stanv/apt/apt.conf.sisyphus.x86_64 --hsh-workdir=/build/stanv/hasher/ std-smp
или
$ time ./buildkernel-hsh --target=x86_64 --hsh-workdir=/home/stanv/hasher --hsh-options='--apt-config=/home/stanv/apt/apt.conf.sisyphus.x86_64 --repo=/home/stanv/tmp/repo-2.6.23 --target=x86_64' wks

Сборка дополнительных модулей

См. статью Сборка модулей ядра.

A

Каждый пакет, несущий дополнительный модуль собирается на основе шаблона. Шаблоны для всех дополнительных модулей раньше можно было загрузить с CVS:

$ cvs -d cvs.alt:/cvs/kernel checkout -d modules kernel/modules
или
$ cvs -d anoncvs@anoncvs.altlinux.org:/cvs/kernel co -d modules kernel/modules

Теперь шаблоны для модулей находятся в репозиториях kernel-modules у мантейнеров.

B

Например, при сборке пакета kernel-modules-nvidia-std-smp-100.14.19-alt3.132631.1.i586.rpm будет использован шаблон modules/nvidia/kernel-modules-nvidia.spec и пакет kernel-source-nvidia-1001419-100.14.19-alt39.i586.rpm.

Пакет kernel-source-nvidia-1001419-100.14.19-alt39.i586.rpm берем из Sisyphus.

Пакеты kernel-source-* собираются как обычно. У кого-то лежит в гите, у кого-то старым дедовским способом. Получается что мантейниры модулей предлагают только kernel-source-%modulename, а сам бинарный модуль собирает vsu. Пакеты с бинарными модулями нужно собирать с каждым обновлением ядра. Если kernel-source-modulename плохо собран, тогда vsu выполняет двойную работу, либо забивает на этот модуль.

Заметки

На patch_level_numeric (1.0.0) фактически забили. Он был нужен, когда собирали pre/rc

Undeground

то есть, rpm-build-kernel — для BuildRequires, kernel-build-tools — скрипты для использования мантейнерами

pull . сейчас можно менять на merge что лучше cherry-pick или pull ? это в древних версиях git merge не предназначался для вызова руками зависит от ситуации… если в ветке куча коммитов, которые в свежей версии уже есть, merge с большой вероятностью не пройдёт автоматически если это патчи, которые не вошли в новую версию, вероятно, лучше сделать merge а я сделал cherry :( кстати, в подобном случае может иметь смысл сначала сделать merge новой версии в эту ветку хотя это зависит от того, что в дальнейшем предполагается делать с этими изменениями если нужно получить патчи для свежего апстрима, придётся делать rebase если это какие-то изменения, которые апстриму нафиг не нужны, может быть проще смержить свежую версию апстрима туда и разгрести конфликты кстати, в самом свежем git сделали поддержку revert и cherry-pick для merge… указывается, с каким родителем делать дифф, который потом откатывается или применяется A->B ы :(то есть cherry-pick может забирвать все коммиты, между A и B ? нет… это git rebase умеет только он портит исходный бранч а в чем тогда новая фишка ? cherry-pick и revert — это почти одно и то же, различаются тем, в какую сторону применяется патч патч генерируется между указанным коммитом и его родителем если это merge, нужно указать, какой из родительских коммитов нужно брать вот эту опцию и добавили то есть, если сделать cherry-pick для merge, получится один мегапатч со всеми изменениями вообще это полезно для revert

Ссылки

Примечания

  1. Athlon 64 X2 Dual Core 3800+ и 1GB ОЗУ, по субьективной оценке, не очень быстро работают