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

第13回 起動の仕組みを読む

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

カーネル段階

ブートローダから処理を委ねられたカーネルは,まず初期化用ramdiskを展開,マウントして,ルートファイルシステムをマウントするために必要なモジュールドライバ類を組み込みます。

初期化用ramdiskから組み込まれるモジュールドライバは使用しているSCSIアダプタやUSBコントローラに応じたドライバ,LVM構築に必要なドライバ,ext3ファイルシステム用のドライバなどです。なお,SCSIアダプタやUSBコントローラなどのハードウェア環境に応じたドライバは,インストーラがシステムインストール時に検出したハードウェアを元に用意されるので,initrdファイルをハードウェア構成が異なる環境に持っていくと動作しない場合があります。

初期化用ramdiskから必要なモジュールドライバを組み込んだカーネルは,それらのドライバも利用しながらハードウェアの認識や初期化を進めていきます。カーネルには動作を調整するための設定ファイルはありませんが,ブートローダから渡されるカーネルパラメータでさまざまな調整が可能になっています。

UNIX/Linuxでは,ほとんどのコマンドが設定ファイルで動作を調整することが可能なのに,なぜご本尊たるカーネルには設定ファイルが無いのでしょうか?

答は簡単で,設定ファイルを読みだすためにはカーネルの機能が必要になりますが,カーネル自身が初期化中の段階ではそのような機能を使えないからです。そのためカーネルの動作は起動時に与えるパラメータでさまざまに調整できるようになっています。また,最近では起動時ramdiskの段階でprocファイルシステムを用いて設定するようなスタイルもあるようです。

起動されたカーネルはCPUやメモリ,接続されている周辺機器の認識や初期化を行い,最終的にはカーネルパラメータで指定されたルートパーティションをマウントして,そこにある /sbin/initを起動し,その後の処理を委ねます。

カーネルはデフォルトでは/sbin/initを起動しますが,カーネルパラメータのinit=...オプションで起動するコマンドを変更することも可能です。たとえば,ブートローダからinit=/bin/bashを指定してやると,カーネルは初期化終了後,/sbin/initではなく/bin/bashを起動して,システムを対話的に操作することが可能になります。このテクニックは正しく起動しなくなった環境を修復する際には便利ですが,rootのパスワードを知らなくてもroot権限での作業ができてしまうので,セキュリティの観点からは注意が必要です。

/sbin/init段階

ハードウェアの認識,初期化を終了したカーネルは/sbin/initを起動し,その後の処理を委ねます。/sbin/initに処理を委ねたカーネルは表の世界からは姿を消し,以後は黒子として世界を支える仕事に徹します。

一方,/sbin/initは全てのプロセスの祖として必要なプロセスを起動していきますが,その際に利用する設定ファイルが/etc/inittab(リスト2)です。

リスト2 /etc/inittabの内容

 1  #
 2  # inittab       This file describes how the INIT process should set up
 3  #               the system in a certain run-level.
 4  #
 5  # Author:       Miquel van Smoorenburg, 
 6  #               Modified for RHS Linux by Marc Ewing and Donnie Barnes
 7  #
 8  
 9  # Default runlevel. The runlevels used by RHS are:
10  #   0 - halt (Do NOT set initdefault to this)
11  #   1 - Single user mode
12  #   2 - Multiuser, without NFS (The same as 3, if you do not have networking)
13  #   3 - Full multiuser mode
14  #   4 - unused
15  #   5 - X11
16  #   6 - reboot (Do NOT set initdefault to this)
17  # 
18  id:5:initdefault:
19  
20  # System initialization.
21  si::sysinit:/etc/rc.d/rc.sysinit
22  
23  l0:0:wait:/etc/rc.d/rc 0
24  l1:1:wait:/etc/rc.d/rc 1
25  l2:2:wait:/etc/rc.d/rc 2
26  l3:3:wait:/etc/rc.d/rc 3
27  l4:4:wait:/etc/rc.d/rc 4
28  l5:5:wait:/etc/rc.d/rc 5
29  l6:6:wait:/etc/rc.d/rc 6
30  
31  # Trap CTRL-ALT-DELETE
32  ca::ctrlaltdel:/sbin/shutdown -t3 -r now
33  
34  # When our UPS tells us power has failed, assume we have a few minutes
35  # of power left.  Schedule a shutdown for 2 minutes from now.
36  # This does, of course, assume you have powerd installed and your
37  # UPS connected and working correctly.  
38  pf::powerfail:/sbin/shutdown -f -h +2 "Power Failure; System Shutting Down"
39  
40  # If power was restored before the shutdown kicked in, cancel it.
41  pr:12345:powerokwait:/sbin/shutdown -c "Power Restored; Shutdown Cancelled"
42  
43  
44  # Run gettys in standard runlevels
45  1:2345:respawn:/sbin/mingetty tty1
46  2:2345:respawn:/sbin/mingetty tty2
47  3:2345:respawn:/sbin/mingetty tty3
48  4:2345:respawn:/sbin/mingetty tty4
49  5:2345:respawn:/sbin/mingetty tty5
50  6:2345:respawn:/sbin/mingetty tty6
51  
52  # Run xdm in runlevel 5
53  x:5:respawn:/etc/X11/prefdm -nodaemon

/etc/inittabも他の設定ファイル同様,#から行末までがコメントと見なされるので,17行目まではコメント,18行目が最初の設定行です。

/etc/inittabでは1つの行が1つの設定になっており,各行は :(コロン)で4つの欄に分割されています。各欄の意味は,最初の欄がそれぞれの設定を区別するためのラベル,2つめがその設定が動作するランレベルの指定,3つめがどのような動作を行なうかの指定,4つめが起動するプロセスの指定になります。

前回も簡単に触れましたが,⁠ランレベル」というのはシステムの動作モードを意味し,レベルによって設定する機能やサービスを変えて,システムを安全かつ効率よく運用するための仕組みです。それぞれのレベルの意味はディストリビューションによって多少異なりますが,ランレベル0がシステムの停止モード,6が再起動モード,1がシングルユーザモードというのは共通しています。

それ以外のモードをどのように使うかはディストリビューションごとに異なり,Red Hat系のディストリビューションでは,9行目から17行目に記されているように,2が(セキュリティ等の問題がある場合に)NFS機能を使わないマルチユーザモード,3が標準のマルチユーザモード,4は未使用で,5がログイン時にもX Window Systemを用いるGUIモードになります。

3つめの動作欄にinitdefaultと指定した18行目がデフォルトのランレベルの設定で,ここでは5がデフォルトのランレベルとなります。

デフォルトのランレベルは起動時のカーネルパラメータに数字を指定することで変更することができます。また,動作中に telinitコマンドを用いて変更することも可能です。

動作欄にsysinitと指定した21行目がシステムの初期化処理の指定です。/sbin/initはこの行を見てシステムの初期化のために/etc/rc.d/rc.sysinitを起動します。

23行目から29行目が /etc/rc.d/rc.sysinitを実行してから,それぞれのランレベルで実行すべき処理の指定です。具体的には,それぞれのランレベル(0から6)を引数に /etc/rc.d/rcというスクリプトを実行するようになっています。これらの行では動作欄(3つめの欄)が wait とされており,指定したランレベルになった際に 4 つめの欄に指定したプロセスを実行し,プロセスの実行終了まで待つことを意味します。この処理により,それぞれのランレベルに応じたサービス(プロセス)を起動します。

32行目,38行目,41行目はそれぞれ特定の状態になった際の動作の指定です。32行目は,いわゆる「三本指の挨拶(three fingers salute)⁠と呼ばれるctrl+alt+deleteの3つのキーが同時に押された際の動作の指定で,(now)から3秒待ってから(-t3)⁠シャットダウン後再起動するように(-r)指定して/sbin/shutdownコマンドを起動します。

38行目はUPSから電源断の信号が送られてきた際の処理で,2分後に(+2)⁠"Power Failure; System Shutting Down" というメッセージをログファイルに記録して,再起動ではなく停止状態になるように(-h)/sbin/shutdown を起動します。-f の指定は次回の起動時にはファイルシステムのチェック(fsck)を動かさないようにする指定です。

41行目は電源断の信号が届いてからシステムをシャットダウンするまでの2分間に電源回復を示す信号が届いた場合にシャットダウンをキャンセルするための処理です。

45行目から50行目は2から5までのランレベルの際に/sbin/mingettyというプロセスを起動してtty1からtty6までの端末を監視させる指定です。ランレベルは0が halt,6がrebootなので,それ以外のランレベル(動作用のランレベル)ではtty1からtty6の6つの端末からログインできるようになります。

ここで言う「端末」はX Windows System上のgnome-terminal等の端末ソフトウェアではなく,コンソール画面上の仮想端末を意味します。Xを起動していない状態では,Altキーとファンクションキーを同時に押すことで仮想端末を切り替えることができ,45行目から50行目の指定でALT+F1からALT+F6までの6つの仮想端末が同時に利用できるようになります。なお,X上の端末ソフトウェアはここで言う仮想端末とは異なる仕組みで動いているので,6つという数字に制限されず,いくつでも同時に起動することが可能です。

これらの指定の動作欄に指定されているrespawnは,プロセス欄に指定したプロセスが終了すれば再度同じプロセスを起動することを意味します。この指定により,コンソール画面からログアウト(/sbin/mingetty を終了)しても,同じコンソール画面に再度ログインメッセージが表示(/sbin/mingettyの再起動)されるようになります。

53行目はX Window Systemを用いたログイン処理の指定で,/etc/X11/prefdmというコマンド(実体はシェルスクリプト)を用いて利用可能なディスプレイマネージャ(X用のログイン管理ソフトウェア)を起動しています。スクリプトの中では/etc/sysconfig/desktopの指定に基づいてGNOME用やKDE用のディスプレイマネージャを切り替えるようになっています。

以上,ざっと/etc/inittabの設定を眺めてきましたが,この設定ファイルによる/sbin/initの動作を整理してみます。

/sbin/initはまず18行目でデフォルトのランレベルが5であることを認識します。一方,21行目のsysinitの指定で,まず最初に/etc/rc.d/rc.sysinitを起動します。その後,デフォルトのランレベルである5に入って,ランレベル5の際に実行すべき処理を実行していきます。まず 28 行目で/etc/rc.d/rc 5を実行し,その終了まで待ちます(wait)⁠

41行目にもランレベル5で実行すべき処理がありますが,この処理はpowerokwaitの指定でUPSから特別な信号が入ったという条件の際に実行することになります。

次に45行目から50行目の指定で/sbin/mingettyを6つの仮想端末に対して実行し,コンソールからのログインを待ちます。最後に53行目の指定により/etc/X11/prefdm経由でX Window System用のディスプレイマネージャを起動します。その際にはXウィンドウやGNOME/KDEといったデスクトップ環境も必要になるので,それらも合わせて起動されることになります。

前回紹介したrc.sysinitはこの/sbin/initの処理の流れの中で,システムの初期化用に実行される最初のスクリプトというわけです。

著者プロフィール

こじまみつひろ

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

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