ソースコード・リテラシーのススメ

第14回 initrdを読む

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

# ls -l bin
合計 804K
-r-xr-xr-x 1 root root 614K 2008-06-03 06:13 lvm
-rwxr-xr-x 1 root root  81K 2008-06-03 06:13 modprobe
-rwxr-xr-x 1 root root  80K 2008-06-03 06:13 nash
-rwxr-xr-x 1 root root 8.4K 2008-06-03 06:13 rmmod

このディレクトリにあるのが初期化用ramdisk内で動作するコマンドです。

lvmは最近のfedora coreが採用しているLVM(Logical Volume Manager)を制御するコマンドで,HDD上のrootファイルシステム自身がLVM上に構築されているため,初期化用ramdiskでLVMを読む準備をしておく必要があります。

modprobermmodはモジュールドライバを組み込んだり取り外したりするコマンド,nashはRed Hatが開発している初期化用ramdisk用のコマンドインタプリタです。nashはシェルの一種のような名称を持っていますが,通常のシェルのような対話機能は持たず,初期化用ramdisk用の初期化スクリプトを実行するための機能に特化しています。

# ls -l lib
合計 2.6M
drwx------ 3 root root 4.0K 2008-06-03 06:13 i686
-rwxr-xr-x 1 root root 143K 2008-06-03 06:13 ld-2.7.90.so
lrwxrwxrwx 1 root root   12 2008-06-03 06:13 ld-linux.so.2 -> ld-2.7.90.so
lrwxrwxrwx 1 root root   20 2008-06-03 06:13 libblkid.so.1 -> /lib/libblkid.so.1.0
 ..
drwx------ 3 root root 4.0K 2008-06-03 06:13 modules

/libディレクトリには /bin以下のコマンドが利用するライブラリが収められています。Fedora Coreの場合,初期化用ramdiskにも通常のCライブラリ(libc-2.7.90)を使っているようです。

/lib/modulesディレクトリには初期化用ramdiskで組み込まれるモジュールドライバが収められています。今回,VMware Server環境用に組み込まれたモジュールドライバは以下の通りでした。

# ls -lh lib/modules/2.6.25-0.163.rc7.git1.fc9.i686/
合計 764K
-rw------- 1 root root  67K 2008-06-03 06:13 BusLogic.ko
-rw------- 1 root root  32K 2008-06-03 06:13 dm-mirror.ko
-rw------- 1 root root  62K 2008-06-03 06:13 dm-mod.ko
-rw------- 1 root root  23K 2008-06-03 06:13 dm-snapshot.ko
-rw------- 1 root root 7.0K 2008-06-03 06:13 dm-zero.ko
-rw------- 1 root root  38K 2008-06-03 06:13 ehci-hcd.ko
-rw------- 1 root root 129K 2008-06-03 06:13 ext3.ko
-rw------- 1 root root  55K 2008-06-03 06:13 jbd.ko
-rw------- 1 root root  13K 2008-06-03 06:13 mbcache.ko
-rw------- 1 root root  892 2008-06-03 06:13 modules.alias
-rw------- 1 root root   69 2008-06-03 06:13 modules.ccwmap
-rw------- 1 root root 1.3K 2008-06-03 06:13 modules.dep
-rw------- 1 root root   73 2008-06-03 06:13 modules.ieee1394map
-rw------- 1 root root  141 2008-06-03 06:13 modules.inputmap
-rw------- 1 root root   81 2008-06-03 06:13 modules.isapnpmap
-rw------- 1 root root   74 2008-06-03 06:13 modules.ofmap
-rw------- 1 root root  645 2008-06-03 06:13 modules.pcimap
-rw------- 1 root root   43 2008-06-03 06:13 modules.seriomap
-rw------- 1 root root 7.6K 2008-06-03 06:13 modules.symbols
-rw------- 1 root root  189 2008-06-03 06:13 modules.usbmap
-rw------- 1 root root  27K 2008-06-03 06:13 ohci-hcd.ko
-rw------- 1 root root 155K 2008-06-03 06:13 scsi_mod.ko
-rw------- 1 root root 6.1K 2008-06-03 06:13 scsi_wait_scan.ko
-rw------- 1 root root  33K 2008-06-03 06:13 sd_mod.ko
-rw------- 1 root root  28K 2008-06-03 06:13 uhci-hcd.ko

これらのうち,BusLogic.koscsi_mod.koscsi_wait_scan.kosd_mod.koがVMware ServerがエミュレートしているBusLogic製のSCSIアダプタとそれを経由して利用するSCSI HDD用のドライバモジュールです。

dm-mirror.kodm-mod.kodm-snapshot.kodm-zero.koはLVM用のデバイスマッパー用のドライバモジュール,ext3.kojbd.kombcache.koはext3形式でフォーマットしたrootファイルシステム用のドライバモジュール,echi-hcd.koohci-hcd.kouhci-hcd.koはUSBホストコントローラ用のドライバモジュールです。

modules.alias等,modules.XXX という名称のファイルはモジュールドライバ用の設定ファイルで,モジュールドライバの別名定義やそれぞれのモジュールドライバが対応するハードウェアのリストになっています。

この初期化用ramdiskが仮のrootファイルシステムとしてマウントされると,カーネルは/initを実行します。このファイルは先に紹介したnash用のスクリプトになっていますので,まず先頭部分を眺めてみます。

リスト1

 1  #!/bin/nash
 2  
 3  mount -t proc /proc /proc
 4  setquiet
 5  echo Mounting proc filesystem
 6  echo Mounting sysfs filesystem
 7  mount -t sysfs /sys /sys
 8  echo Creating /dev
 9  mount -o mode=0755 -t tmpfs /dev /dev
10  mkdir /dev/pts
11  mount -t devpts -o gid=5,mode=620 /dev/pts /dev/pts
12  mkdir /dev/shm
13  mkdir /dev/mapper
14  echo Creating initial device nodes
15  mknod /dev/null c 1 3
16  mknod /dev/zero c 1 5
17  mknod /dev/systty c 4 0
...

1行目はスクリプトのお約束であるシェバンの指定です。実際の処理の始まりである3行目で各種情報を利用するためにprocファイルシステム,7行目でsysファイルシステムをマウントします。次に,udevを用いて動的にデバイスファイルを生成するため,メモリ上に生成されるtmpファイルシステムを/devにマウントして(9行目)⁠/dev 上に必要なデバイスファイルを生成していきます(15行目以下)⁠

通常のシェルスクリプトの場合は,mountやechoはシステム上に存在するコマンドを実行しますが,初期化用ramdisk内には先に/binを見たようにmountやechoといったコマンドは存在していません。また,HDD上のrootファイルシステムはまだマウントしていないので,そこに存在するコマンドを利用することもできません。それではこれらのコマンドはどこにあるのでしょうか?

実は,これらのコマンドはnashの内部コマンドで,nash自身がmountやmknodの処理を行えるようになっています。 この種の⁠スイス・アーミー・ツール⁠はbusyboxが有名ですが,初期化用ramdisk専用のツールを作ってしまうところに Red Hatの力を感じます。

その後,42行目あたりから /lib/modules ディレクトリに用意されたモジュール類を組み込んでいきます。

リスト2

42  echo "Loading ehci-hcd module"
43  modprobe -q ehci-hcd
44  echo "Loading ohci-hcd module"
45  modprobe -q ohci-hcd
46  echo "Loading uhci-hcd module"
...

HDDとファイルシステムを読み込むために必要なモジュールを組み込んだ後,LVM用のモジュールを組み込んだ上で,lvmコマンドを実行して論理ボリュームを利用可能にします(73行目)⁠

リスト2

70  echo Scanning logical volumes
71  lvm vgscan --ignorelockingfailure
72  echo Activating logical volumes
73  lvm vgchange -ay --ignorelockingfailure  VolGroup00
74  resume /sys/block/dm-1
75  echo Creating root device.
76  mkrootdev -t ext3 -o defaults,ro /dev/VolGroup00/LogVol00
77  echo Mounting root filesystem.
78  mount /sysroot
79  echo Setting up other filesystems.
80  setuproot
81  loadpolicy
82  echo Switching to new root and running init.
83  switchroot
84  echo Booting has failed.
85  sleep -1

その後,nashは76行目で論理ボリューム上のファイルシステムをrootファイルシステムとして設定し,78行目でそれをマウント,新しくマウントしたファイルシステムをrootファイルシステムとして設定し(80行目)SELinuxのポリシーファイルを読み込んだ上で(81行目)⁠新しいrootファイルシステムに切り替える(83行目)⁠という処理を行ないます。この処理の結果,rootファイルシステムが初期化用ramdiskからHDD上の本来のrootファイルシステムに切り替わり,以後の処理はHDD上(実際はHDDを抽象化したLVM上)のrootファイルシステムの/sbin/initの仕事になります。

初期化用ramdiskの使い方はディストリビューションごとに大きく異なり,今回紹介したFedora Core以外にも,SUSEやDebianなどさまざまなディストリビューションが独自の考え方から初期化用ramdiskを活用しています。考え方はディストリビューションごとに異なりますが,cpio+gzipという形式は共通していますので,今回紹介した手順で一度自分の使っている初期化用ramdiskを調べてみるのも面白いでしょう。

著者プロフィール

こじまみつひろ

Plamo Linuxとりまとめ役。もともとは人類学的にハッカー文化を研究しようとしていたのが,いつの間にかミイラ取りがミイラになってOSSを仕事にするようになってしまいました。最近はスペシャリスト養成を目的とした専門職大学院で教壇に立ったりもしています。

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