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

第10回 Plamo-7.1とinitrd[1]

この記事を読むのに必要な時間:およそ 5 分

前回簡単に紹介したように,新元号が施行された勢いに便乗して,約1年ぶりのバージョンアップとなるPlamo Linux 7.1をリリースしました。

図1 www.plamolinux.orgのリリースアナウンス

図1 www.plamolinux.orgのリリースアナウンス

もっとも最近では,新しいパッケージは随時FTPで公開していて,get_pkginfoコマンドでFTP上のパッケージと同期を取るのも簡単なので,⁠バージョンアップ」といっても,含まれているソフトウェアにそれほど目新しいものはありません。

しかしながら,Plamo-7.0でデフォルトの文字コードをUTF-8に変更したことに続き,今回のPlamo-7.1でもシステムレベルではかなり大きな変更を加えています。それが今回取りあげるinitrdの採用です。

もっともinitrd自体は古くからある技術ですし,Plamo以外のディストリビューションではたいていinitrdを採用しているので,いまさら,という気はするものの,この機会にinitrdの仕組みや動作の流れを紹介してみます。

initrdとinitramfs

Linuxでは,周辺機器用のドライバはカーネル本体とは独立したモジュールとしてビルドでき,/lib/modulesディレクトリ以下から必要に応じて組み込めるようになっています。しかしながら/lib/modulesディレクトリを使うためには,ハードディスク用のドライバとルートファイルシステムに応じたファイルシステム用のドライバが必要で,これらをモジュール化すると「缶詰の中に缶切りが入った」状態になってしまいます。

このような状況を回避するために考案されたのがinitrdです。initrdは,ハードディスクとファイルシステム用のドライバを/lib/modulesとは別に用意しておいて,カーネルがルートファイルシステムをマウントする前に必要なモジュールを組み込んでしまおう,という仕組みです。

initrdの歴史は古く,ソースコードのDocumentation/admin-guide/initrd.rstを見ると,文書の初版は1996年になっています(多分,linux-1.3シリーズの後期)⁠もっとも,当初のinitrdは,INITial RamDiskの名前通り,あらかじめファイルとして作成しておいたファイルシステムをメモリ上に割り当てたram diskにマウントする,というスタイルで,固定サイズのファイルシステムイメージを用意しなければならない等,使い勝手はよくありませんでした。

そのため後になると,ブロックデバイスのram diskではなく,ディスクキャッシュを汎用化する形で実装されたramfsの機能を使うinitramfsが開発されました(2005年前後,linux-2.5の後期)⁠

initramfsはinitrdと同じ機能を果すものの,あらかじめファイルシステムを用意する必要が無く,使いたいコマンドやライブラリを集めたcpioアーカイブを作るだけで利用できるため,急速にinitrdに取って代わりました。しかしながら,grub等のブートローダでは"initrd=...."という指定が定着していることもあり,最近ではinitrd/initramfsの双方を"initrd"という名前で呼ぶようになっています。そのため,Plamo-7.1で採用したのは正確にはinitramfsなものの,通称であるinitrdで通しておきます。

前述のように,initrdはHDDやファイルシステムのようなルートファイルシステムを読み込むのに必要なドライバを,起動時に直接カーネルに組み込む仕組みで,カーネル本体の機能はできるだけ小さくして,必要な機能は環境に応じて動的に組み込むマイクロカーネル的なデザインにするなら必須の機能になります。

しかしながら,モノリシックカーネルであるLinuxでは,ルートファイルシステムをマウントするのに必要なドライバはあらかじめカーネル本体に組み込んでおくことも可能で,カーネル本体が多少大きくなっても構わなければinitrdを使う必要はありません。

一般ユーザ向けのPCを前提にすれば,HDD用のドライバはSATA(libata)だけで間に合いますし,ファイルシステムもext2/3/4系とxfs,btrfsくらいで充分なので,この程度ならカーネル組み込みでも問題ないだろう,と考えて,従来のPlamo Linuxではinitrdを使っていませんでした。

しかしながら最近では,ノートPCを中心にeMMCNVMeといった新しいブロックデバイスが普及してきたり,USBも3.0になるとUAS(USB Attached SCSI)のようにSCSI機能と絡んできたりして,組み込まなければならないドライバがずいぶん増加し,ドライバ間の依存関係もずいぶん複雑になってきた上,新しいドライバも日々増加し続けています。

その結果,make menuconfigでカーネル構築時の設定を決める際も,どのドライバを組み込み,どれをモジュールにすべきかにずいぶん悩むようになりました。それならいっそモジュールにできるドライバは全部モジュールにして,組み込むかどうかはカーネル自身に任せた方がいいんじゃないかと考えて,Plamo-7.1ではあらかじめ用意したinitrdイメージをカーネルパッケージに含めることにしたわけです。

次節以降で紹介するように,initrdは仕組み的にはそれほど難しいわけではないものの,どのコマンドやライブラリ,ドライバ・モジュールを含めるかを0から考えていくのはかなり面倒です。そこで今回も,BLFSプロジェクトで紹介されているスクリプトを元に,Plamo用に多少アレンジして採用することにしました。

Plamo-7.1のinitrd

initrdの実体は,ドライバ・モジュールとそれをカーネルに組み込むためのツール一式をcpio形式で固めて圧縮したファイルです。このファイルのことをinitrdイメージと呼ぶことにしましょう。

initrdイメージがどのような作りになっているのか,実際のファイルを展開しながら紹介します。なお,カーネルパッケージは随時バージョンアップするので,バージョン番号は適宜読み替えてください。

Plamo-7.1のカーネルパッケージはplamolinux.orgからダウンロードできます。このパッケージに含まれているboot/initrd.img-4.19.35_plamo64というファイルがinitrdイメージなので,まずパッケージからこのファイルを取り出します。Plamo Linuxのパッケージは単純なtar+xz形式なので,tarコマンドでファイルを取り出すことができます。

$ tar xvf kernel-4.19.35-x86_64-B1.txz boot/initrd.img-4.19.35_plamo64
boot/initrd.img-4.19.35_plamo64
$ ls -lh boot
合計 17M
-rwxr--r--+ 1 kojima users 17M  4月 25日  11:37 initrd.img-4.19.35_plamo64*

約17MBのinitrdイメージが取り出せました。このファイルは,cpio形式のアーカイブをgzipで圧縮した形になっているため,展開する際はzcatコマンドを通してからcpioを適用する必要があります。取り出したファイルはカレント・ディレクトリ以下にばらまかれるので,まずはInitrdという作業用ディレクトリを作り,そこでinitrdイメージを展開します。

$ mkdir Initrd ; cd Initrd
$ zcat ../boot/initrd.img-4.19.35_plamo64 | cpio -ivd
.
init
lib64
etc
etc/lvm
etc/lvm/cache
etc/lvm/lvm.conf
...
bin/cat
bin/sh
51847 ブロック

展開したinitrdイメージの中身を見ると,/devや/proc,/sysを含む,シンプルなルートファイルシステムになっています。

$ ls
bin/  dev/  etc/  init*  lib/  lib64@  proc/  run/  sbin/  sys/  usr/

Linuxのお手本であるUNIXでは,起動したカーネルは必要な初期化処理を終えれば,ルートファイルシステム上にある/sbin/initコマンドを起動することになっています。この流儀を崩さずに必要な処理を実行するため,initrdはいったん仮のルートファイルシステムを提供し,そこにあるinitコマンドを実行させてカーネルに必要なモジュールを組み込むわけです。

このinitはシェルスクリプトなので,つまみ読みしながら動作を紹介してみましょう。

著者プロフィール

こじまみつひろ

Plamo Linuxとりまとめ役。もともとは人類学的にハッカー文化を研究しようとしていたものの,いつの間にかミイラ取りがミイラになってOSSの世界にどっぷりと漬かってしまいました。最近は田舎に隠棲して半農半自営な生活をしながらソフトウェアと戯れています。

URLhttp://www.linet.gr.jp/~kojima/Plamo/index.html