○initrd の仕組み
Plamo-7.1で採用したinitrdは、正式には initramfs と呼ばれる仕組みで、 カーネルと共にブートローダ(grub)によってメモリに読み込んだファイルから、 root filesystem をマウントするために必要なモジュール類を カーネルに組み込むために使われます。
最初に生まれた initrd は、INITialize RamDisk の名前通り、 あらかじめ loopback 機能等を用いてファイルの形で作成した ファイルシステムをRAMディスク上に展開するスタイルでした。 その後、あらかじめファイルシステムを用意しなくても利用できる ramfs が開発され、そこに任意サイズのcpioアーカイブを展開すれば ファイルシステムとして利用できるようになりました。 この第2世代の仕組みは initramfs という名称なものの、 grubのパラメータ等では initrd= ... という書式が定着しているので、 initramfs 用のファイルでも、名称は initrd.img-XXXX を使うという 慣習になっています。そのため、本稿でも initrd/initramfs の総称として initrd を使っています。
initrdは、LiveCD等でも使われるものの、 主な用途はroot filesystem(fs)をマウントするために必要な モジュール類のロードです。
Linuxも従っているUnixの伝統的な流儀では、 起動されたカーネルはCPUや周辺機器の初期化等、必要な処理を終えれば、 root fsをマウントし、 そこにある init コマンドに以後の処理を委ねるようになっています。
この処理の流れを大きく変えずに済むように、 initrd にはカーネルから処理を引き継ぐinitコマンドが用意され、 そのinitコマンドが必要とするツールやライブラリ一式を組み込んだ、 シンプルなroot filesystemになるように設計されています。
Plamo-7.1で採用しているinitrdは以下のような構造になっています。
$ ls bin/ dev/ etc/ init* lib/ lib64@ proc/ run/ sbin/ sys/ usr/
ここにある init はシェルスクリプトで、 udevd を起動して接続されている周辺機器を確認し、 必要なモジュール類をカーネルに読み込ませてから、 カーネルパラメータの root=... で指定された真のroot fsをマウントし、 最終的に、switch_rootコマンドでroot fsを切り替える、という処理を行います。
後述する mkinitramfs が利用できるように、initrd用のinitスクリプトは /usr/share/mkinitramfs/init.in に収められているので、 動作を確認したい方はこのファイルをご参照下さい。
この init はシェルスクリプトなので、動かすためにはshell(bash)が必要です。 また、周辺機器の認識用の udevd、 必要なモジュールをロードする modprobe、 root fsをマウントするためのmount等が必要で、 さらにそれらが利用する各種ライブラリ等も必要となり、 それら一式が/binや/lib以下のディレクトリに収められています。
$ ls bin basename* cp* insmod@ kmod* ls* mkdir* mount* rm* sh* umount* cat* dd* killall* ln* lsmod@ mknod* readlink* sed* sleep* uname* $ ls lib firmware/ libcap.so.2* libm.so.6* libudev.so.1* ld-linux-x86-64.so.2* libdevmapper-event.so.1.02* libmount.so.1* libuuid.so.1* libacl.so.1* libdevmapper.so.1.02* libncursesw.so.6* libz.so.1* libattr.so.1 libdl.so.2* libpthread.so.0* modules/ libblkid.so.1* libkmod.so.2* libreadline.so.7* udev/ libc.so.6* liblzma.so.5* librt.so.1* $ ls sbin blkid* lvdisplay@ lvscan@ pvchange@ pvscan@ vgchange@ vgscan@ dmsetup* lvextend@ mdadm* pvck@ switch_root* vgck@ lvchange@ lvm* mdmon* pvcreate@ udevadm* vgcreate@ lvcreate@ lvrename@ modprobe* pvdisplay@ udevd* vgrename@
これらのファイルを含むため、Plamo-7.1の initrd は、圧縮状態で20MB程、 展開すると30MB程度のサイズになります。
initrd は小さい方が読み込み時間が短くてすみ、起動速度も速くなるため、 かっては busybox 等を使ってサイズを削減する取り組みが行なわれていました。 しかしながら、昨今のハードウェア環境ではそれほどサイズを気にする必要も無くなってきたので、 最近では標準のglibc一式を使って、実環境と互換性を持たせた設計に変ってきています。
このinitrdにはカーネルのドライバ・モジュールが含まれているので、 カーネルを更新する際にはinitrdも合わせて更新する必要があります。 そこで、Plamo-7.1では initrd を作成するための /sbin/mkinitramfs というコマンドを用意しました。
/sbin/mkinitramfs は、 LFS方面で開発されたシェルスクリプトをPlamo用に調整したもので、 必要なディレクトリ構造やデバイスファイルを作り、 システム環境から各種コマンドやライブラリをコピーした上で、 root fsをマウントする際に必要となりそうなモジュール類をコピーし、 cpioアーカイブにまとめた上で圧縮する、という処理を行います。
具体的にどのようなファイル/モジュールをコピーするのかを知りたい方は、 /sbin/mkinitramfs をご覧ください。
mkinitramfs は initrd 上にデバイスファイルを作成するため、 実行にはroot権限が必要となります。
$ ls /lib/modules/ 4.19.35/ 4.19.35-plamo64/ 5.1.5-plamo64/ $ sudo /sbin/mkinitramfs 5.1.5-plamo64 [sudo] kojima のパスワード: Creating initrd.img-5.1.5-plamo64... . ... $ ls -lh initrd.img-5.1.5-plamo64 -rw-r--r-- 1 root root 20M 6月 1日 12:48 initrd.img-5.1.5-plamo64
こうして作成したinitrdをカーネルと同じディレクトリ(/boot)に配置し、 /sbin/grub-mkconfig を実行すれば、 このinitrdを利用するgrub.cfgが作成されます。 以下の例では、test.cfg として試作しています。
$ sudo /sbin/grub-mkconfig -o test.cfg Generating grub configuration file ... Linux イメージを見つけました: /boot/vmlinuz-5.1.5-plamo64 Found initrd image: /boot/initrd.img-5.1.5-plamo64 Linux イメージを見つけました: /boot/vmlinuz-4.19.35_plamo64 Found initrd image: /boot/initrd.img-4.19.35_plamo64 Found Windows Boot Manager on /dev/sda2@/efi/Microsoft/Boot/bootmgfw.efi Found Plamo Linux release 7.0 on /dev/sda6 Found Plamo Linux release 7.0 on /dev/sda7 Found Plamo Linux release 7.0 on /dev/sdb3 完了
作成した設定ファイルを、MBR起動の場合は /boot/grub/grub.cfg、 UEFI起動の場合はESP(EFI System Partition)を/boot/efi にマウントした上で /boot/efi/grub/grub.cfg にコピーすれば、 新しく登録したカーネルやinitrdを起動することができます。
なお、grub-mkconfigはカーネルとinitrdを バージョン番号(上記例では 5.1.5-plamo64)で対応づけるので、 両者が一致している必要があります。 特にPlamo環境では、"-"(ハイフン)と"_"(アンダースコア)を混同しがちなのでご注意ください。