12.2. FreeBSD の起動プロセス

計算機の電源を入れ、オペレーティングシステムをスタートさせるのには、 おもしろいジレンマがあります。定義により、 計算機は、オペレーティングシステムが起動するまでは、 ディスクからプログラムを動かすことも含めて、 何をどうすればよいかまったく知りません。 計算機はオペレーティングシステムなしにディスクからプログラムを実行することができず、 オペレーティングシステムのプログラムがディスク上にあるのなら、 どうやってオペレーティングシステムを起動するのでしょうか?

この問題はほらふき男爵の冒険 という本の中に書かれている問題ととてもよく似ています。 登場人物がマンホールの下に半分落っこちて、 靴紐 (ブートストラップ) をつかんで自分を引っぱり、持ち上げるのです。 計算機の黎明期には、ブートストラップ という用語でオペレーティングシステムをロードする機構のことを指していました。 いまはこれを縮めて ブート (起動) と言います。

x86 ハードウェアでは、基本入出力システム (Basic Input/Output System: BIOS) にオペレーティングシステムをロードする責任があります。 BIOS はハードディスク上のマスターブートレコード (Master Boot Record: MBR) を探します。 MBR はハードディスク上の特定の場所になければなりません。 BIOS には MBR をロードし起動するのに十分な知識があり、 オペレーティングシステムをロードするために必要な作業の残りは、 場合によっては BIOS の助けを得た上で MBR が実行できることを仮定しています。

注記:

FreeBSD は古い標準の MBR、 または新しい GUID Partition Table (GPT) から起動できます。 GPT パーティションは、Unified Extensible Firmware Interface (UEFI) に対応したコンピュータで良く用いられます。 しかしながら、FreeBSD はレガシーな BIOS にのみに対応したコンピュータからも、gptboot(8) により、 GPT パーティションから起動できます。 UEFI からの直接の起動への対応は進行中です。

MBR 内部のコードは、 一般的にブートマネージャと呼ばれます。 とりわけユーザとの対話がある場合にそう呼ばれます。 通常ブートマネージャのもっと多くのコードが、 ディスクの最初のトラック、またはファイルシステム上におかれます。 ブートマネージャの例としては、Boot Easy とも呼ばれる FreeBSD 標準のブートマネージャの boot0、 多くの Linux® ディストリビューションが採用している Grub 等があります。

ディスク上にインストールされているオペレーティングシステムが 1 つの時は、MBR はディスク上の最初の起動可能な (アクティブな) スライスを探し、 そのスライスにあるコードを起動してオペレーティングシステムの残りをロードします。 ディスク上に複数のオペレーティングシステムが存在しているのなら、 複数のオペレーティングシステムの一覧を表示できて、 起動するオペレーティングシステムを選択できるような、 別のブートマネージャをインストールすることもできます。

FreeBSD のブートストラップシステムの残りは 3 段階に分かれます。 第 1 ステージは、 計算機を特定の状態にするために必要なことだけを知っていて、 第 2 ステージを起動します。 第 2 ステージでは、第 3 ステージを起動する前に、 もう少しできることがあります。 第 3 ステージでオペレーティングシステムのロード作業を完了します。 起動作業が 3 段階に分かれているのは、 MBR がステージ 1 とステージ 2 で実行できるプログラムのサイズに制限を課しているからです。 これらの作業をつなぎ合わせることによって、 FreeBSD はより柔軟なローダ (loader) を提供しているのです。

その後カーネルが起動し、デバイスの検出と初期化を開始します。 そしてカーネルの起動が終わると、制御はユーザープロセスの init(8) へ移されます。init(8) はディスクが利用可能であることを確認し、 ファイルシステムのマウント、 ネットワークで利用するネットワークカードのセットアップ、 そしてブート時に起動されるように設定されたプロセスの起動、 といったユーザーレベルでのリソース (資源) 設定を行ないます。

この章では、これらのステージについてより詳細に、また、FreeBSD ブートプロセスにおける対話的な設定方法について説明します。

12.2.1. ブートマネージャ

MBR のブートマネージャのコードは起動プロセスの第 0 ステージと呼ばれることがあります。 デフォルトでは、FreeBSD は boot0 を使います。

FreeBSD のインストーラがインストールする MBR は、 /boot/boot0 を基にしています。 boot0 のサイズと機能は、 スライステーブルおよび MBR 末尾の識別子 0x55AA のため、 446 バイトの大きさに制限されます。 もし、boot0 と複数のオペレーティングシステムをインストールした場合、 起動時に以下のようなメッセージが表示されます。

例12.1 boot0 のスクリーンショット
F1 Win
F2 FreeBSD

Default: F2

他のオペレーティングシステムは、 FreeBSD の後にインストールを行うと、既存の MBR を上書きしてしまいます。 もしそうなってしまったら、 もしくは既存の MBR を FreeBSD の MBR で置き換えるには、 次のコマンドを使ってください。

# fdisk -B -b /boot/boot0 device

device は起動するデバイス名で、 たとえば 1 番目の IDE ディスクは ad0、2 番目の IDE コントローラに接続されている 1 番目の IDE ディスクは ad2、 1 番目の SCSI ディスクは da0 などとなります。 MBR の設定をカスタマイズしたい場合は、 boot0cfg(8) を参照してください。

12.2.2. 起動ステージ 1 と起動ステージ 2

概念上、第 1 ステージと第 2 ステージはハードディスクの同じ領域上の同一のプログラムの部分部分です。 スペースの制約のため 2 つに分割されていますが、 いつも一緒にインストールされます。 FreeBSD のインストーラまたは bsdlabel は、 両者を 1 つにまとめた /boot/boot をコピーします。

これらの 2 つのステージは、ファイルシステムの外部、 起動スライスの最初のトラックに置かれ、 先頭が最初のセクタにきます。 boot0 またはその他のブートマネージャは、 起動プロセスを続けるために必要なプログラムがそこにあると想定しています。

最初のステージの boot1 は、 512 バイトの大きさでなければならないという制限があるので、 非常に単純なプログラムです。 このプログラムは boot2 を検索して実行するため、そのスライスの情報を保持する FreeBSD の BSD ラベル に関する最低限の情報だけを持っています。

次のステージの boot2 はもう少し高機能です。 これは FreeBSD のファイルシステム上でファイルを見つける機能を持ちます。 実行するカーネルやローダを指定するための簡単なインタフェースを提供します。 boot2 により起動される loader はさらに高機能で、 起動設定が行なえる手段を提供します。 ステージ 2 で起動プロセス中断した時には、 次のようながインタラクティブなが画面が表示されます。

例12.2 boot2 のスクリーンショット
>> FreeBSD/i386 BOOT
Default: 0:ad(0,a)/boot/loader
boot:

インストールされた boot1boot2 を変更するには、 bsdlabel を使ってください。 以下の例では、diskslice は起動するディスクとスライスで、たとえば最初の IDE ディスクの 1 番目のスライスは ad0s1 となります。

# bsdlabel -B diskslice

警告:

ad0 のようにディスク名だけを指定すると、 bsdlabel は、スライスを持たない 危険な専用モードを作成してしまいます。 これはおそらく、あなたが望んでいることではないでしょうから、 Return キーを押す前に、 diskslice の部分を二重にチェックしてください。

12.2.3. 起動ステージ 3

loader は三段階の起動プロセスの最終段階です。 これは通常、ファイルシステム上の /boot/loader として存在しています。

loader は、 よりさまざまなコマンド群をサポートした強力なインタプリタによって提供される組み込みコマンド群を利用することで、 インタラクティブな設定手段となるように設計されています。

loader は初期化の際にコンソールとディスクの検出を行ない、 どのディスクから起動しているかを調べます。 そして必要な変数を設定してからインタプリタを起動し、 スクリプトからコマンドを送ったり手でコマンドを入力したりできます。

loader は次に /boot/loader.rc を読み込み、通常、変数の標準値を定義した /boot/defaults/loader.conf と、そのコンピュータにローカルに変数を定義した /boot/loader.conf を読み込みます。 loader.rc はそれらの変数にもとづき、 選択されたモジュールとカーネルをロードします。

loader は最後に、 標準設定で 10 秒のキー入力待ち時間を用意し、 入力がなければカーネルを起動します。 入力があった場合、コマンド群が使えるプロンプトが表示され、 ユーザは変数を調整したり、すべてのモジュールをアンロードしたり、 モジュールをロードしたりすることができます。 その後、最終的な起動や再起動へ移行します。 表12.1「ローダの組み込みコマンド」では、 もっともよく使われる loader のコマンドをまとめています。 利用可能なコマンドをすべて知りたい場合には、 loader(8) を参照してください。

表12.1 ローダの組み込みコマンド
変数説明
autoboot secondsseconds で与えられた時間内に入力がなければ、 カーネルの起動へと進みます。 カウントダウンを表示します。標準設定では 10 秒間です。
boot [-options] [kernelname]すぐにカーネルの起動へ進みます。 オプション、カーネル名が指定されている場合は、 それらが使われます。 unload を実行後、 カーネル名をコマンドラインから指定することができます。 unload を実行しないと、 一度読み込まれたカーネルが使われます。 kernelname でパスが指定されていない時には、 /boot/kernel および /boot/modules から調べられます。
boot-confすべてのモジュールの設定を、 起動時と同じように指定された変数 (最も多いのは kernel) にもとづいて自動的に行ないます。 このコマンドは、変数を変更する前に、 最初に unload を行なった場合にのみ有効に働きます。
help [topic]/boot/loader.help を読み込み、ヘルプメッセージを表示します。 topic に index が指定された場合、 利用可能な topic の一覧を表示します。
include filename指定されたファイルを読み込み、行単位で解釈します。 エラーが発生した場合、 include の実行は直ちに停止します。
load [-t type] filename指定されたファイル名のカーネル、 カーネルモジュール、あるいは type に指定された種類のファイルをロードします。 filename 以降に指定された引数はファイルへと渡されます。 filename でパスが指定されていない時には、 /boot/kernel および /boot/modules から調べられます。
ls [-l] [path]指定された path にあるファイルを表示します。 path が指定されていなければ、ルートディレクトリを表示します。 -l が指定されていればファイルサイズも表示されます。
lsdev [-v]モジュールがロード可能なすべてのデバイスを表示します。 もし -v が指定されていれば、 より詳細な出力がされます。
lsmod [-v]ロード済みのモジュールを表示します。 -v が指定されていれば、 より詳細な内容が出力されます。
more filenameLINES 行を表示するごとに停止しながら指定されたファイルを表示します。
rebootすぐにシステムを再起動します。
set variable, set variable=valueローダの環境変数を設定します。
unloadすべてのロード済みモジュールを削除します。

次にあげるのは、ローダの実践的な使用例です。 普段使っているカーネルをシングルユーザモードで起動します。

boot -s

普段使っているカーネルとモジュールをアンロードし、 古いもしくは別のカーネルをロードするには、 以下のように実行してください。

unload
load kernel.old

kernel.GENERIC とすると、 インストール時のデフォルトカーネルを指定できます。 また、システムをアップグレードしたり、 もしくはカスタムカーネルを設定した場合に、 直前にインストールされていたカーネルは、 kernel.old で指定できます。

普段のカーネルで使っているモジュールを指定したカーネルでロードする場合は、 次のようにします。

unload
set kernel="kernel.old"
boot-conf

カーネルの自動設定スクリプトをロードします。

load -t userconfig_script /boot/kernel.conf

12.2.4. 最終ステージ

カーネルがデフォルトの loader もしくは loader を迂回して boot2 によって読み込まれると、 起動フラグが調べられ、それに応じて動作が調整されます。表12.2「起動時のカーネルオプション」 には、 良く使われる起動フラグがまとめられています。 他の起動フラグの詳細については、 boot(8) を参照してください。

表12.2 起動時のカーネルオプション
オプション説明
-aカーネル初期化中に、 ルートファイルシステムとしてマウントするデバイスを尋ねます。
-CCDROM からルートファイルシステムを起動します。
-sシングルユーザモードで起動します。
-vカーネル起動時に、より詳細な情報を表示します。

カーネルの起動が完了すると、init(8) というユーザプロセスに制御が移されます。 これは /sbin/init、 もしくは loaderinit_path 変数で指定される場所にあります。 これは起動プロセスの最終ステージです。

起動シーケンスでは、 システム上で利用できるファイルシステムの一慣性を確認します。 もし UFS ファイルシステムにに問題があって fsck が不一致を修復できなければ、 管理者が問題を直接解決できるように、init はシステムをシングルユーザモードへと移行させます。 問題がなければ、システムはマルチユーザモードに移行します。

12.2.4.1. シングルユーザモード

このモードには、ユーザが起動時に -s を指定した場合、あるいは loaderboot_single 変数を設定することによって移行します。 マルチユーザモードから shutdown now を呼び出すことでもこのモードに移行できます。 シングルユーザモードは、以下のメッセージで開始します。

Enter full pathname of shell or RETURN for /bin/sh:

ユーザが Enter を入力すると、 システムは Bourne シェルを起動します。 別のシェルを使うには、シェルのフルパスを入力してください。

シングルユーザモードは、 通常ファイルシステムの一貫性に問題があって起動できないシステムを修復したり、 起動設定ファイルの間違いを修正するために使われます。 また、root パスワードがわからなくなった場合に、 リセットするために使うことも出来ます。 シングルユーザモードのプロンプトは、 ローカルファイルシステムおよび設定ファイルへのアクセスを与えてくれますが、 ネットワーク接続は出来ません。

シングルユーザモードは、システムの修復には有用ですが、 システムが物理的に安全な場所になければ、 セキュリティのリスクがもたらされます。 デフォルトでは、システムに物理的にアクセス可能なユーザは、 シングルユーザモードで起動後はシステムをすべてコントロールできます。

/etc/ttys でシステムの consoleinsecure に設定されている場合、 システムはシングルユーザモードに移行する前に root のパスワードを入力するように求めます。 root パスワードがわからなくなった場合のリセット機能が無効になっている間は、 セキュリティ対策が必要となります。

例12.3 /etc/ttys の insecure コンソール
# name  getty                           type    status          comments
#
# If console is marked "insecure", then init will ask for the root password
# when going to single-user mode.
console none                            unknown off insecure

insecure コンソールとは、 コンソールが物理的に安全でない (insecure) と考えられるため、 root のパスワードを知る人だけがシングルユーザモードを使えるという意味です。

12.2.4.2. マルチユーザモード

init がファイルシステムが正常であると判断するか、 ユーザがシングルユーザモードでのコマンドを終了し、 exit を入力してシングルユーザモードを終了すると、 システムはマルチユーザモードへ移行し、 システムのリソースの設定を開始します。

リソース設定システムはデフォルト設定を /etc/defaults/rc.conf から、 また、システム独自の細かな設定を /etc/rc.conf から読み込みます。 そして /etc/fstab に記述されるシステムファイルシステムをマウントします。 その後、ネットワークサービス、さまざまなシステムデーモン、 そして最後に、ローカルにインストールされた package の起動スクリプトを実行します。

リソース設定システムについてもっと知りたい場合には、 rc(8) を参照してください。また、/etc/rc.d にあるスクリプトを実行してみてください。

本文書、および他の文書は ftp://ftp.FreeBSD.org/pub/FreeBSD/doc/ からダウンロードできます。

FreeBSD に関する質問がある場合には、 ドキュメント を読んだ上で <questions@FreeBSD.org> まで (英語で) 連絡してください。

本文書に関する質問については、 <doc@FreeBSD.org> まで電子メールを (英語で) 送ってください。