Ubuntu 16.04カーネルを再ビルドする手順を記載します。
できるかぎりUbuntu 16.04カーネルが用意している仕組みを用いるようにしている為、Makefileであるdebian/rulesを利用しており、mainlineカーネルをビルドしてインストールする方法とは異なる部分が多いです。
Table of Contents
1 カーネルビルドに必要なパッケージのインストール
libncurses5-devはmake menuconfigの為にインストールします。
$ sudo apt build-dep -y linux $ sudo apt install -y libncurses5-dev
2 ソースコードの取得
特定のバージョンのカーネルを利用したい場合はdeb-srcからソースコードを取得し、最新のバージョンや全てのバージョンのカーネルを利用したい場合はgitリポジトリからソースコードを取得します。
fakeroot debian/rules distcleanを実行した場合は以下を実行する必要があります。
fakeroot debian/rules cleanの場合は必要ありません。
$ fakeroot debian/rules debian/control $ cp debian.master/changelog debian/
2.1 deb-srcからソースコードを取得
debian/scripts/配下のスクリプトに実行権限を与える必要があります。また一度distcleanしないとコンパイルエラーが発生します。
$ mkdir linux.ubuntu-16.04 $ cd linux.ubuntu-16.04 $ apt source linux $ cd linux-4.4.0 $ chmod -R u+x debian/scripts/* $ fakeroot debian/rules distclean $ fakeroot debian/rules debian/control $ cp debian.master/changelog debian/
2.2 gitリポジトリからソースコードを取得
deb-srcの場合とほぼ同様です。
$ git clone git://git.launchpad.net/~ubuntu-kernel/ubuntu/+source/linux/+git/xenial $ cd xenial $ fakeroot debian/rules debian/control $ cp debian.master/changelog debian/
3 changelogの変更
作成するdebファイル名のsuffixを変更する為にchangelogを編集します。
debchangeでchangelogを編集できます。
$ sudo apt-get install -y devscripts $ EDITOR=emacs debchange
以下の内容を先頭に追加しました。debファイルのsuffixにubuntu1が追加されます。
linux (4.4.0-22.39ubuntu1) UNRELEASED; urgency=medium * Hello, Linux -- <hiroom2@ubuntu-16.04> Mon, 16 May 2016 17:52:06 +0900
4 カーネルコンフィグの変更
editconfigsでカーネルコンフィグを変更します。
ここではamd64/config.flavour.genericのみを変更します。
$ fakeroot debian/rules editconfigs dh_testdir; /bin/bash -e debian/scripts/misc/kernelconfig editconfigs Do you want to edit config: amd64/config.flavour.generic? [Y/n] Y make[1]: Entering directory '/home/hiroom2/src/linux.ubuntu-16.04/linux-4.4.0' make[2]: ディレクトリ '/home/hiroom2/src/linux.ubuntu-16.04/linux-4.4.0/build' に入ります HOSTCC scripts/basic/fixdep GEN ./Makefile HOSTCC scripts/kconfig/mconf.o SHIPPED scripts/kconfig/zconf.tab.c SHIPPED scripts/kconfig/zconf.lex.c SHIPPED scripts/kconfig/zconf.hash.c HOSTCC scripts/kconfig/zconf.tab.o HOSTCC scripts/kconfig/lxdialog/checklist.o HOSTCC scripts/kconfig/lxdialog/util.o HOSTCC scripts/kconfig/lxdialog/inputbox.o HOSTCC scripts/kconfig/lxdialog/textbox.o HOSTCC scripts/kconfig/lxdialog/yesno.o HOSTCC scripts/kconfig/lxdialog/menubox.o HOSTLD scripts/kconfig/mconf scripts/kconfig/mconf Kconfig
make menuconfigの画面が表示されます。
セーブすると反映されます。
ここではamd64/config.flavour.lowlatency以降のコンフィグは使わないのでnでスキップします。
.config:4244:warning: override: M686 changes choice state configuration written to .config *** End of the configuration. *** Execute 'make' to start the build or try 'make help'. make[2]: ディレクトリ '/home/hiroom2/src/linux.ubuntu-16.04/linux-4.4.0/build' から出ます make[1]: Leaving directory '/home/hiroom2/src/linux.ubuntu-16.04/linux-4.4.0' Do you want to edit config: amd64/config.flavour.lowlatency? [Y/n] n <snip> check-config: 31/43 checks passed -- exit 1 *** ERROR: 12 config-check failures detected
config-checkスクリプトでエラーが表示されますが、もともとのコンフィグでも表示されるので無視します。
5 ソースコード変更
すでに一度ビルドを実行した後でソースコードを変更した場合は、debian/stamp/stamp-build-genericを削除してから再ビルドを実行する必要があります。
ここではinit実行前に"Hello, Linux"と表示する変更を加えます。
diff --git a/init/main.c b/init/main.c index 9e64d70..1ecc819 100644 --- a/init/main.c +++ b/init/main.c @@ -933,6 +933,8 @@ static int __ref kernel_init(void *unused) { int ret; + printk("Hello, Linux"); + kernel_init_freeable(); /* need to finish all async __init code before freeing the memory */ async_synchronize_full();
6 ファイル名のバージョン変更(bad know-how)
changelogを変更しただけではdebファイルの名前が変更されるだけで、その中身のカーネルイメージ等のファイル名は変更されません。
debファイルをインストールすると既存のカーネルイメージが上書きされてしまいます。
こういう場合は通常、カーネルコンフィグのCONFIG_LOCALVERSIONを用いるのですが、CONFIG_LOCALVERSIONを有効にするとdebian/rulesでビルドエラーが発生してしまいます。
そこで、相当強引な方法ですが、abi_suffixを用いてファイル名の末尾にsuffixを追加します
。abi_suffixに-helloを設定することで、ファイル名のバージョンに無理やり-helloというsuffixを加えることで上書きを回避します。
$ export abi_suffix=-hello
abi_suffixを使とxenial/drivers/hv/hv.cがコンパイルエラーになるのを防ぐ為に、debian/rulesを編集します。
diff --git a/debian/rules.d/0-common-vars.mk b/debian/rules.d/0-common-vars.mk index 1c87ebd..2b1fa67 100644 --- a/debian/rules.d/0-common-vars.mk +++ b/debian/rules.d/0-common-vars.mk @@ -224,7 +224,7 @@ kmake = make ARCH=$(build_arch) \ CONFIG_DEBUG_SECTION_MISMATCH=y \ KBUILD_BUILD_VERSION="$(uploadnum)" \ LOCALVERSION= localver-extra= \ - CFLAGS_MODULE="-DPKG_ABI=$(abinum)" + CFLAGS_MODULE="-DPKG_ABI=$(shell echo $(abinum) | sed 's/$(abi_suffix)//g')" ifneq ($(LOCAL_ENV_CC),) kmake += CC=$(LOCAL_ENV_CC) DISTCC_HOSTS=$(LOCAL_ENV_DISTCC_HOSTS) endif
abi_suffixをexportした後、ebian/controlを作成しなおしてください。
debian/controlで-helloが付いたファイル名が記載されます。
$ fakeroot debian/rules debian/control
7 ビルド
一度ビルドを実行している場合の為に、いくつかのファイルを削除します。
$ rm -rf debian/stamps/stamp-build-generic $ rm -rf debian/linux-image-extra-*/lib/modules/*/kernel/kernel
ビルド時間を短縮する為、do_tools=falseでlinux-cloud-toolsを生成しないようにします。
lowlatencyというflavorのカーネルをビルドするにはbinary-genericをbinary-lowlatencyに変更して下さい。
より多くのCPUコアを持つ環境ならば、parallel=2の値をコア数の分だけ大きくするとビルド速度が向上します。
$ DEB_BUILD_OPTIONS=parallel=2 do_tools=false no_dumpfile=1 \ fakeroot debian/rules binary-generic
ひとつ上のディレクトリにdebファイルが作成されました。
$ ls ../*.deb linux-headers-4.4.0-22-hello-generic_4.4.0-22.39ubuntu1_amd64.deb linux-image-4.4.0-22-hello-generic_4.4.0-22.39ubuntu1_amd64.deb linux-image-extra-4.4.0-22-hello-generic_4.4.0-22.39ubuntu1_amd64.deb
debファイルをインストールします。
4.4.0-22-helloというsuffixを持つファイルがインストールされています。
$ sudo dpkg -i linux-image-4.4.0-22-hello-generic_4.4.0-22.39ubuntu1_amd64.deb $ ls /boot/ System.map-4.4.0-21-generic initrd.img-4.4.0-22-generic System.map-4.4.0-22-generic initrd.img-4.4.0-22-hello-generic System.map-4.4.0-22-hello-generic initrd.img-4.4.0-22-mykernel-generic abi-4.4.0-21-generic lost+found abi-4.4.0-22-generic memtest86+.bin abi-4.4.0-22-hello-generic memtest86+.elf config-4.4.0-21-generic memtest86+_multiboot.bin config-4.4.0-22-generic vmlinuz-4.4.0-21-generic config-4.4.0-22-hello-generic vmlinuz-4.4.0-22-generic grub vmlinuz-4.4.0-22-hello-generic initrd.img-4.4.0-21-generic
buntu 16.04を再起動します。
$ sudo reboot
ESCキーでGRUBメニューを表示させ、"Advanced options for Ubuntu"を選択させると先ほど追加したカーネルのエントリが追加されています。
カーネルログにHello, Worldと追加され、カーネルのバージョンも変わりました。
$ dmesg | grep -2 "Hello, Linux" [ 0.029550] Freeing SMP alternatives memory: 28K (ffffffff820b3000 - ffffffff820ba000) [ 0.034677] ftrace: allocating 31906 entries in 125 pages [ 0.064341] Hello, Linux [ 0.064360] smpboot: Max logical packages: 1 [ 0.064362] smpboot: APIC(0) Converting physical 0 to logical package 0 $ $ uname -r 4.4.0-22-hello-generic