Ubuntuのカーネル再構築

以前、Redhat系のCentOSカーネルを再構築したが(「CentOSのカーネル再構築」)、今回はUbuntuDebian系)の再構築を試みた。
カーネル本体はディストリビューションとは独立しているので基本的なやり方は同じだが、Debianではカーネルの再構築用のユーティリティ(スクリプト等)を提供しているので、それらを使って簡単に構築できる。
次のような手順となる。

  1. 環境の整備(開発環境パッケージの追加)
  2. ソースコード・パッケージのダウンロード
  3. ソースコードの展開
  4. カーネルコンパイル
  5. カーネルのインストール

本来は3と4の間にカーネル構成の設定があるが、今回は先ず現在動いているカーネルと同じ構成のものを作ることを目的としたので省略した。

 環境の整備

Ubuntuはインストールしたての状態でコンパイルの環境が十分ではないためまず、一応、コンパイラの環境を整える。

root@ubuntu804:~# apt-get install build-essential

ただし、これを実行しなくても、後でカーネルソースのパッケージをインストールする時に

The following packages were automatically installed and are no longer required:
  g++-4.2 libtimedate-perl g++ libstdc++6-4.2-dev dpkg-dev patch

というメッセージが出るので、自動的に必要最低限の環境は整えられる。

次にカーネルの再構築に必要となるパッケージをインストールするが、後でカーネルソースのパッケージをダウンロード時に次のパッケージを推奨としているメッセージが出る。

Suggested packages:
  kernel-package libncurses-dev ncurses-dev libqt3-dev

“kernel-package”はmake-kpkg等のカーネル構築用コマンドを含むのでダウンロードしておいた方が良いと思う。(カーネル本体の構築はディストリビューションに関係ないので、必ずしも必要でないが、Debianの環境で構築しやすい環境を整えるので使った方が無難だろう。)
“libncurses-dev”、“ncurses-dev”は後でmake menuconfigを使ってカーネル構築のパラメータを設定する場合に必要となる。ちなみに“libncurses-dev”または“ncurses-dev”をインストールしようとすると自動的に“libncurses5-dev”がインストールされる。(次のxconfigを使う場合は必要ない。)
“libqt3-dev”は後でmake xconfigを使う場合に必要。ただし、libqt3-devをインストールしようとすると、パッケージが見つからない旨のメッセージが出る。

Package libqt3-dev is not available, but is referred to by another package.
This may mean that the package is missing, has been obsoleted, or
is only available from another source

そこで代わりに“libqt3-mt-dev”をインストールすればxconfigが使える。(上のmenuconfigを使う場合は必要ない。)
“make menuconfig”でも“make xconfig”でもなくvi等を使って直接“.config”を変更する場合は、libncurses5-devやlibqt3-mt-devのどちらも必要ないが、素直に使った方が無難だろう。

root@ubuntu804:~# apt-get install kernel-package
root@ubuntu804:~# apt-get install libncurses5-dev
root@ubuntu804:~# apt-get install libqt3-mt-dev

 ソースコード・パッケージのダウンロード

利用可能なソースコードパッケージを確認する。

root@ubuntu804:~# apt-cache search linux-source
linux-source - Linux kernel source with Ubuntu patches
linux-source-2.6.24 - Linux kernel source for version 2.6.24 with Ubuntu patches
root@ubuntu804:~# 

ここで該当するパッケージ名が出てこない場合がある。その場合は“apt-get check”を実行してから再度apt-cache searchを実行すると表示できた。

目的のソースコードパッケージをタウンロードする。

root@ubuntu804:~# apt-get install linux-source-2.6.24

ダウンロードが完了すると /usr/src/linux-source-2.6.24.tar.bz2 が作られる。

 ソースコードの展開

root@ubuntu804:~# cd /usr/src
root@ubuntu804:/usr/src# ls
linux-headers-2.6.24-21          linux-source-2.6.24.tar.bz2
linux-headers-2.6.24-21-generic
root@ubuntu804:/usr/src# tar xf linux-source-2.6.24.tar.bz2
root@ubuntu804:/usr/src# ls
linux-headers-2.6.24-21          linux-source-2.6.24
linux-headers-2.6.24-21-generic  linux-source-2.6.24.tar.bz2
root@ubuntu804:/usr/src# 

(最近のtarは“z”や“j”などの圧縮形式を指定しなくても自動的に判断して解凍してくれる。便利と言えば便利である。)

 カーネルコンパイル

まず、/bootの下から現在使っているカーネルを作成した時のコンフィグファイルをコピーして来て、これから作るカーネルコンパイル環境に反映させる作業(make oldconfig)を行うのが定石だ。(勿論、現在のカーネルの構成に関係なく新規に作る場合は必要ない。)

root@ubuntu804:/usr/src# cd linux-source-2.6.24
root@ubuntu804:/usr/src/linux-source-2.6.24# cp /boot/config-2.6.24-21-generic .config
root@ubuntu804:/usr/src/linux-source-2.6.24# make oldconfig

しかし、この状態で次のようにdiffを取って見ると、

root@ubuntu804:/usr/src/linux-source-2.6.24# diff /boot/config-2.6.24-21-generic .config
2c2,4
< # Common config options automatically generated by splitconfig.pl
---
> # Automatically generated make config: don't edit
> # Linux kernel version: 2.6.24-22-generic
> # Mon Nov  3 22:42:48 2008
4,5d5
< CONFIG_3C359=m
< CONFIG_60XX_WDT=m
7,95c7,28
	:
	:

内容が大幅に書き変わっていることが分かる。本当に元の内容と同じなのか、次のようなコマンドで試してみた。(プロンプトが長いので省略してる。)

# grep -v "^#" /boot/config-2.6.24-21-generic | sort -u > c1
# grep -v "^#" .config | sort -u > c2
# diff c1 c2
0a1
> 
#

空行が増えているだけで、実質的に/bootからコピーして来たコンフィグと変わらないことが分かる。
なお、明示的に“make oldconfig”を実行しなくても.configが変更されていると次に実行するmake-kpkgで自動的にmake oldconfigを実行してくれるので、わざわざ実行する必要もない。(が、念のために手動で実行しておいた方が無難だろう。)

この段階でカーネルの構成(コンフィグレーション)を変更するのであれば、make oldconfigに続けてmake menuconfig等を実行する。ただし、今回は現在のカーネルと全く同じものを作ってみるだけなので省略する。

これで用意が整ったので、カーネルを作成する。

root@ubuntu804:/usr/src/linux-source-2.6.24# make-kpkg --initrd --revision=test.0.1 kernel_image

このコマンドは私の環境で62分位かかった。終了すると /usr/srcに新しいカーネルをインストールするためのパッケージファイル“linux-image-2.6.24.3_test.0.1_amd64.deb”が作られている。

 カーネルのインストール

make-kpkgが作成したパッケージファイルをdpkgコマンドでインストールする。

root@ubuntu804:/usr/src/linux-source-2.6.24# cd ..
root@ubuntu804:/usr/src# ls
linux-headers-2.6.24-21                  linux-source-2.6.24
linux-headers-2.6.24-21-generic          linux-source-2.6.24.tar.bz2
linux-image-2.6.24.3_test.0.1_amd64.deb
root@ubuntu804:/usr/src# 
root@ubuntu804:/usr/src# dpkg -i linux-image-2.6.24.3_test.0.1_amd64.deb
root@ubuntu804:/usr/src# 
root@ubuntu804:/usr/src# ls -l /boot
total 64908
-rw-r--r-- 1 root root   420395 2008-10-22 10:49 abi-2.6.24-21-generic
-rw-r--r-- 1 root root    74177 2008-10-22 10:49 config-2.6.24-21-generic
-rw-r--r-- 1 root root    79175 2008-11-02 18:17 config-2.6.24.3
drwxr-xr-x 2 root root     4096 2008-11-03 14:35 grub
-rw-r--r-- 1 root root  7821253 2008-11-02 11:37 initrd.img-2.6.24-21-generic
-rw-r--r-- 1 root root  7734980 2008-11-02 10:23 initrd.img-2.6.24-21-generic.bak
-rw-r--r-- 1 root root 43975920 2008-11-03 14:35 initrd.img-2.6.24.3
-rw-r--r-- 1 root root   103204 2007-09-28 20:03 memtest86+.bin
-rw-r--r-- 1 root root  1153201 2008-10-22 10:49 System.map-2.6.24-21-generic
-rw-r--r-- 1 root root  1153201 2008-11-02 19:08 System.map-2.6.24.3
-rw-r--r-- 1 root root  1905688 2008-10-22 10:49 vmlinuz-2.6.24-21-generic
-rw-r--r-- 1 root root  1905080 2008-11-02 19:08 vmlinuz-2.6.24.3
root@ubuntu804:/usr/src# 

/boot/grub/menu.lstも自動的に変更してくれるので、あとはリブートすれば新しいカーネルで立ち上がる。

 なぜバージョンが2.6.24.3なのか

現在使っているカーネルのコンフィグファイルである config-2.6.24-21-generic を元に新カーネルも作ったのに、新カーネルのバージョンは 2.6.24-21-generic ではなく 2.6.24.3 となっている。2.6.24 以下のバージョン文字(EXTRAVERSION)は .configの方で指定するのではなくMakefileの方で指定している。Makefileの4行目を次のように変更して

EXTRAVERSION = -22-generic

カーネルを作成すると、作成されたカーネルバージョンは 2.6.24-22-generic となる。