続・玩式草子 ―戯れせんとや生まれけん―

第12回Plamo-7.1とinitrd[3]

過去2回に渡ってPlamo Linux 7.1で新規に採用したinitrdの仕組みや作り方を紹介してきました。今回はこの話題のまとめとしてinitrdを使ったカーネル更新の方法を紹介します。なお今回取りあげる予定だったCPUのfirmware(microcode)更新の話題は、紙幅の都合で次回に延期しました。

ソースコードのダウンロードと展開

まずはビルドしたいカーネルのソースコードをwww.kernel.org等からダウンロードします。最近のLinuxカーネルは、Linusさんを中心とした開発チームが公開するバージョン番号が2ケタの開発版(5.0, 5.1, 5.2..)とそれを引き継いだメンテナチームが公開するバージョン番号が3ケタのメンテナンス版(5.0.1, 5.0.2, 5.1.1...)があり、メンテナンス版の中でもっともバージョン番号が大きいもの(本稿執筆時点では5.2.9)最新の安定版(Latest Stable)という扱いになっています。

このバージョン番号が3ケタのメンテナンス版は、開発版のバージョンが2つほど進むとメンテナンスが終わります。すなわち、本稿執筆時点では5.1のシリーズと5.2のシリーズがメンテナンスされているものの、5.1シリーズはEOL(End Of Life:開発終了)が宣言されており、linux-5.3が公開されれば、メンテナンスされるのは5.2と5.3のシリーズになります。数ヶ月後、linux-5.4が公開されると5.2シリーズがEOLとなってメンテナンス対象は5.4と5.3のシリーズになるわけです。

今回は最新の安定版である5.2.9を使うことにしましょう。まず、適切なディレクトリを用意し、ソースコードをダウンロード、展開します。カーネルのビルドは一般ユーザでも可能なので、ホームディレクトリにLinuxというディレクトリを作り、そこでビルドすることにします。

$ mkdir ~/Linux ; cd ~/Linux
$ wget https://cdn.kernel.org/pub/linux/kernel/v5.x/linux-5.2.9.tar.xz
--2019-08-25 22:58:10--  https://cdn.kernel.org/pub/linux/kernel/v5.x/linux-5.2.9.tar.xz
....
linux-5.2.9.tar.xz      100%[=======================================================>] 102.11M  8.19MB/s 時間 12s     
2019-08-25 22:58:23 (8.32 MB/s) - `linux-5.2.9.tar.xz' へ保存完了 [107065760/107065760]

$ tar xvf linux-5.2.9.tar.xz
linux-5.2.9/
linux-5.2.9/.clang-format
linux-5.2.9/.cocciconfig
....
linux-5.2.9/virt/lib/Makefile
linux-5.2.9/virt/lib/irqbypass.c
$

カーネルの各種機能の設定

次にビルドする機能やドライバを設定します。その際、0から全てを設定するのは大変なので、既存の設定を元に新しい機能を追加することにします。Plamo Linuxのデフォルトカーネルでは、/proc/config.gzにそのカーネルをビルドした時の設定を記録しているので、これを.configのヒナ型にします。

$ cd linux-5.2.9
$ zcat /proc/config.gz > .config

この状態でmake oldconfigを実行すると、.configにある設定はそのまま使い、.configに存在しない(=新しく追加された)項目のみを尋ねてくるので、設定すべき項目はだいぶ少なくなります。

$ make oldconfig
 HOSTCC  scripts/basic/fixdep
 HOSTCC  scripts/kconfig/conf.o
 ...
 Cputime accounting
> 1. Full dynticks CPU time accounting (VIRT_CPU_ACCOUNTING_GEN)
choice[1]: 1
Fine granularity task level IRQ time accounting (IRQ_TIME_ACCOUNTING) [Y/n/?] y
BSD Process Accounting (BSD_PROCESS_ACCT) [Y/n/?] y
  BSD Process Accounting version 3 file format (BSD_PROCESS_ACCT_V3) [Y/n/?] y
Export task/process statistics through netlink (TASKSTATS) [Y/?] y
  Enable per-task delay accounting (TASK_DELAY_ACCT) [Y/?] y
  Enable extended accounting over taskstats (TASK_XACCT) [Y/n/?] y
    Enable per-task storage I/O accounting (TASK_IO_ACCOUNTING) [Y/n/?] y
Pressure stall information tracking (PSI) [N/y/?] (NEW)

ここで"(NEW)"と表示されているのが既存の.configには無い設定項目です。選択肢は"[N/y/?]"で、デフォルトでは"N"が設定されているため、このままリターンキーを押せば"N"(使用しない)になります。また、"?"を押せばこの項目に関する説明が表示されるので、どういう機能か知りたい時に使ってみるのもいいでしょう。ちなみに、この項目ではこういう説明が表示されました。

Pressure stall information tracking (PSI) [N/y/?] (NEW) ?

CONFIG_PSI:

Collect metrics that indicate how overcommitted the CPU, memory,
and IO capacity are in the system.

If you say Y here, the kernel will create /proc/pressure/ with the
pressure statistics files cpu, memory, and io. These will indicate
the share of walltime in which some or all tasks in the system are
delayed due to contention of the respective resource.

In kernels with cgroup support, cgroups (cgroup2 only) will
have cpu.pressure, memory.pressure, and io.pressure files,
which aggregate pressure stalls for the grouped tasks only.

For more details see Documentation/accounting/psi.txt.

Say N if unsure.

この説明によると、この機能を"Y"にすると、CPUやメモリ、I/O入出力がリソース不足で待たされた時間の情報が/proc/pressure/以下に出力されるようになるそうです。

ちょっと面白そうな機能ではあるものの、このような情報が必要になるのは仮想環境を大規模にホスティングしているサーバマシンくらいでしょうから、たいていの環境はデフォルトの"N"のままでよさそうです。最後にある"Say N if unsure"の1行も、⁠通常の環境では不要⁠⁠、ということを示しています。

このように、それぞれの設定項目には適切なデフォルト値があらかじめ用意されているので、深く考えずにリターンキー連打で進めていっても大丈夫です。

新しいカーネルのビルドとドライバ・モジュールのインストール

make oldconfigが最後まで進むと.configが更新されます。これでカーネルがビルド可能になったので、環境に応じた並列度を"-j"オプションに指定してビルドします。手元では4コア8スレッドのRyzen5 CPUを使っているので、make -j6で実行、フルビルドには約40分かかりました。

choice[1-3?]: 1
#
# configuration written to .config
#

$ make -j6
SYSHDR  arch/x86/include/generated/asm/unistd_32_ia32.h
SYSTBL  arch/x86/include/generated/asm/syscalls_32.h
SYSTBL  arch/x86/include/generated/asm/syscalls_64.h
....
LD [M]  sound/x86/snd-hdmi-lpe-audio.ko
LD [M]  sound/xen/snd_xen_front.ko
LD [M]  virt/lib/irqbypass.ko
$

次にmake modules_installコマンドで新しくビルドしたドライバ・モジュールをインストールします。モジュールは/lib/modules/以下にインストールされるので、コマンドの実行にはroot権限が必要です。

$ sudo make modules_install
[sudo] kojima のパスワード: ****
  INSTALL arch/x86/crypto/aegis128-aesni.ko
  INSTALL arch/x86/crypto/aegis128l-aesni.ko
  INSTALL arch/x86/crypto/aegis256-aesni.ko
  ...
  INSTALL virt/lib/irqbypass.ko
  DEPMOD  5.2.9-plamo64

/lib/modules/5.2.9-plamo64/以下にインストールされたドライバ・モジュールの総数は5216個でした。

$ find /lib/modules/5.2.9-plamo64 -type f -name "*ko.xz" | wc -l
5216

initrdイメージの作成とインストール

mkinitramfsコマンドで新しくインストールしたドライバ・モジュールを組み込んだinitrdイメージを作ります。/lib/modules/以下には複数バージョンのモジュールが併存していることがあるので、どのバージョンを使うかは引数で指定します。また、initrdイメージ内にはデバイスファイルも作成されるので、作成にはroot権限が必要になります。

$ sudo mkinitramfs 5.2.9-plamo64
[sudo] kojima のパスワード: ****
Creating initrd.img-5.2.9-plamo64... .
...
done.
$ ls -lh initrd.img-5.2.9-plamo64
rw-r--r-- 1 root root 20M  8月 27日  13:35 initrd.img-5.2.9-plamo64

新しく作成したカーネルイメージとinitrdイメージを/bootディレクトリに移します。x86_64アーキテクチャの場合、カーネルイメージはarch/x86/bootディレクトリにbzImageという名前で作成されるので、このファイルを/boot/vmlinuz-5.2.9-plamo64にコピーします。後述するgrub-mkconfigは、カーネルとinitrdイメージをバージョン名("-5.2.9-plamo64")を手掛りに結び付けるので、両者が一致するように注意してください。

$ ls -lh arch/x86/boot/bzImage 
-rw-r--r-- 1 kojima users 6.3M  8月 27日  11:42 arch/x86/boot/bzImage
$ sudo cp arch/x86/boot/bzImage /boot/vmlinuz-5.2.9-plamo64
$ sudo cp initrd.img-5.2.9-plamo64 /boot
$ ls /boot/*5.2.9*
/boot/initrd.img-5.2.9-plamo64  /boot/vmlinuz-5.2.9-plamo64

grub.cfgの作成

grub-mkconfigコマンドで、新しくインストールしたカーネルとinitrdイメージを反映したブートローダ用設定ファイル(grub.cfg)を作ります。設定ファイルの出力先は-oオプションで指定できるので、まずはnew_grub.cfgというファイルに書き出してみます。なお、grub-mkconfigの実行にはroot権限が必要です。

$ sudo grub-mkconfig -o new_grub.cfg
[sudo] kojima のパスワード: ****
Generating grub configuration file ...
Linux イメージを見つけました: /boot/vmlinuz-5.2.9-plamo64
Found initrd image: /boot/initrd.img-5.2.9-plamo64
Linux イメージを見つけました: /boot/vmlinuz-4.19.35_plamo64
Found initrd image: /boot/initrd.img-4.19.35_plamo64
Adding boot menu entry for EFI firmware configuration
完了
$

grub-mkconfigは/boot/に用意した新しいカーネルとinitrdイメージを見つけ、new_grub.cfgファイルに5.2.9カーネル用のエントリが作成されました。

$ cat -n new_grub.cfg
 ...
 115          echo    'Linux 5.2.9-plamo64 をロード中...'
 116          linux   /boot/vmlinuz-5.2.9-plamo64 root=UUID=f7fe5914-6986-4d89-9a2a-8ba152dbfacd ro  net.ifnames=0 quiet
 117          echo    '初期 RAM ディスクをロード中...'
 118          initrd  /boot/initrd.img-5.2.9-plamo64
 ...

新しい設定ファイル(new_grub.cfg)を、UEFI環境ならば/boot/efi/grub/grub.cfgに、MBR環境ならば/boot/grub/grub.cfgにコピーします。Plamo LinuxではEFIシステムパーティション(ESP)は自動マウントされないので、UEFI環境の場合、/boot/efi/にESPを手動でマウントしてやる必要があります。また、何かトラブルがあった時のため、元のgrub.cfgも残しておきましょう。

$ sudo mount /dev/sda2 /boot/efi
[sudo] kojima のパスワード: ****
$ sudo mv /boot/efi/grub/grub.cfg{,.org}
$ sudo mv new_grub.cfg /boot/efi/grub/grub.cfg
$ ls -lh /boot/efi/grub
...
-rwxr-xr-x 1 root root 9.5K  8月 27日  14:13 grub.cfg*
-rwxr-xr-x 1 root root 9.1K  8月 23日  15:36 grub.cfg.org*
...

新しいカーネルでのブート

以上の手順で新しくビルド、インストールしたカーネルとinitrdイメージがブートローダの設定ファイル(grub.cfg)に登録できたので、システムをリブートし、新しいカーネルで起動しましょう。

新しいカーネルが動作しているかはunameコマンドで確認できます。

$ uname -a
Linux ryzen 5.2.9-plamo64 #1 SMP PREEMPT Tue Aug 27 11:05:28 JST 2019 x86_64 GNU/Linux

また、dmesgにも起動時の情報が出力されるので、ロードしているカーネル名やカーネルパラメータをチェックできます。

$ dmesg | head
[    0.000000] Linux version 5.2.9-plamo64 (kojima@ryzen) (gcc version 9.1.0 (GCC)) #1 SMP PREEMPT Tue Aug 27 11:05:28 JST 2019
[    0.000000] Command line: BOOT_IMAGE=/boot/vmlinuz-5.2.9-plamo64 root=UUID=f7fe5914-6986-4d89-9a2a-8ba152dbfacd ro net.ifnames=0 quiet
[    0.000000] KERNEL supported cpus:
[    0.000000]   Intel GenuineIntel
[    0.000000]   AMD AuthenticAMD
[    0.000000]   Hygon HygonGenuine
...

これで新しいカーネルを起動できたので、モジュール類を正しくロードしているか、必要なパーティションを正しくマウントできるか、ネットワーク機能が動作しているか、等々を確認しながら、新しいカーネルを使ってみましょう。


今回紹介したカーネルとinitrdを更新する手順は「汎用的」な方法で、この手順でinitrdイメージとgrub.cfgを作れば、Plamo Linuxのデフォルトと同等のカーネルとinitrdが再現できます。

しかしながらPlamo Linuxでは、make menuconfigで確認してもらえばわかるように、SATA回りのドライバとext4ファイルシステムの機能は、モジュール化せずにカーネル組み込みにする、というショートカット的な設定も残しており、ext4 FSなルートパーティションをSATAドライブ上に置く場合、実のところinitrdイメージは必要ありません(笑⁠⁠。

ご自身の環境が該当すると思われる方は、カーネルイメージ(vmlinuz-5.2.9-plamo64)のみを/boot/に置いてgrub.cfgを作成してみてください。うまく行けば、initrdイメージをロード、展開する時間を省くことができます(せいぜい数秒程度ですが⁠⁠。

なお、今回は手順を簡素化するためソースコードにcjk_ttyパッチをあてていないので、コンソールにUTF-8な日本語は表示できません。必要なパッチは手元に用意しているので、興味ある方はお問い合わせください。

おすすめ記事

記事・ニュース一覧