Linux システムの起動に際しては、様々なコンポーネントや処理が介在しています。ファームウエアとハードウエアの初期化処理が完了した後は、マシンのアーキテクチャによって異なりますが、ブートローダ GRUB 2 などを利用してカーネルを起動します。この時点まで到達すると、ようやくオペレーティングシステムが制御できる状況になり、 systemd
が続きを処理するようになります。 systemd
は 「ターゲット」 と呼ばれるセットを提供し、日々の費用やメンテナンス、緊急時用など、それぞれに役割が設定されています。
この章では、誤解を生みやすい用語に関して、詳しい説明を行っています:
init
一般的に 「init」 というと、下記の 2 つの意味があります:
ルートファイルシステムをマウントするための initramfs
の処理
実際のルートファイルシステムをマウントしたあとに実行される、様々なプログラムを起動するためのオペレーティングシステムの処理
いずれの処理に対しても systemd
がその役割を担っています。まず systemd
はルートファイルシステムをマウントするため、 initramfs
内に存在するものが最初に起動され、ルートファイルシステムのマウントが成功すると、最初のプロセスとしてルートファイルシステム内に存在するものが起動され、元のプロセスを置き換えて動作します。このような構造から、 systemd
のプロセスのうち前者を init on initramfs 、後者を systemd と呼びます。
initrd
/ initramfs
initrd
(INITial Ram Disk (初期 RAM ディスク) の略) は一時的なルートファイルシステムのイメージを含むファイルで、カーネルによって読み込まれ、 /dev/ram
からマウントされる仕組みです。このファイルシステムをマウントするには、ファイルシステムドライバが必要となります。
カーネルバージョン 2.6.13 より、 initrd は initramfs
(INITial RAM File System) と呼ばれるようになり、マウント時にファイルシステムのドライバを必要とはしなくなりました。 openSUSE Leap では initramfs
のみを使用しています。ですが、現在も initramfs
は/boot/initrd
というファイル名で保存されることから、今も 「initrd」 と呼ばれることが多くなっています。本章では initramfs
の用語に統一して説明しています。
Linux の起動処理は、複数のフェーズ (段階) に分けられます。それぞれは別々のコンポーネントが使われます:
初期化フェーズでは、マシンのハードウエアの初期化を行い、デバイスの準備を実施します。この処理は、ハードウエアのアーキテクチャによって異なる処理になります。
openSUSE Leap では、全てのアーキテクチャで GRUB 2 を使用しています。アーキテクチャとファームウェアによりますが、 GRUB 2 ブートローダの開始処理は複数の段階に分けることができます。ブートローダの目的は、カーネルと initramfs (初期 RAM ファイルシステム) を読み込むことです。 GRUB 2 についての詳細は、 第12章 「ブートローダ GRUB 2」 をお読みください。
コンピュータの電源を投入すると、 BIOS や UEFI が画面とキーボードを初期化し、メインメモリのテストを行います。この段階では、マシンはストレージメディアにアクセスすることは行いません。続いて現在の日付と時刻と、最も重要な周辺機器類に関する情報を CMOS から読み込みます。起動メディアとそのジオメトリ情報が認識できるようになると、システムは BIOS/UEFI からブートローダに処理を渡します。
従来型の BIOS を搭載したマシンの場合、起動ディスク内の最初の 512 バイト分のデータセクタ (マスターブートレコード、略して MBR) だけを読み込むことができます。 MBR には最小限の機能だけを持つ GRUB 2 を書き込むことができます。この最小限の機能の GRUB 2 には、ファイルシステムのドライバを含む GRUB 2 のメインイメージを読み込むだけの機能が含まれています。メインイメージは MBR と最初のパーティションまでの間のギャップに含まれている (MBR パーティションテーブルの場合) か、もしくは BIOS の起動パーティション内に含まれています (GPT パーティションテーブルの場合) 。メインイメージにはファイルシステムドライバが含まれていますので、ルートファイルシステムにある /boot
にアクセスすることができます。 /boot
には GRUB 2 のメインイメージに対応する追加のモジュールのほか、カーネルや initramfs のイメージが含まれていますので、あとはこれらを読み込めばカーネルに処理を渡すことができるようになります。
暗号化された /boot
を含む暗号化ファイルシステムから BIOS のシステムを起動する場合、暗号化を解くためのパスワードは 2 回入力する必要があります。 1 回目は GRUB 2 が /boot
を解読するために、 2 回目は systemd
が暗号化されたボリュームをマウントするために必要となります。
UEFI のマシンの場合は、従来型の BIOS マシンより簡単です。ファームウェアは GPT パーティションテーブル内の FAT でフォーマットされたパーティションを読み込むことができます (これを EFI システムパーティションと呼び、起動後のシステムでは /boot/efi
にマウントします) ので、このパーティション内に完全機能の GRUB 2 を配置すれば、それを直接読み込んで実行することができるようになります。
BIOS/UEFI のマシンがネットワーク経由での起動に対応している場合は、 PXE と呼ばれる仕組みを利用して起動用のサーバからブートローダを取得することができます。この場合、 BIOS/UEFI 自身がブートローダ機能の一部を持つことになります。あとは起動用のサーバからイメージを取得してシステムを起動しますので、ローカルのハードディスクを全く使用することなくシステムを立ち上げることができます。
ブートローダの処理が終わると、起動処理は全てのアーキテクチャで同じになります。ブートローダはカーネルと initramfs
(RAM ベースの初期ファイルシステム) をメモリに読み込んで、カーネルが動き始めます。
カーネルがメモリ管理機能を設定し、 CPU の種類と機能を検出すると、ハードウエアの準備を行い、 initramfs
として読み込んでおいた、メモリ内にある一時的なルートファイルシステムをマウントします。
initramfs
ファイル #Edit sourceinitramfs
(INITial RAM File System; 初期 RAM ファイルシステム) は小さな cpio アーカイブで、カーネルが RAM ディスク内に読み込むことができる仕組みです。これは /boot/initrd
に配置されるもので、 dracut
というツールで作成することができます (詳しくは man 8 dracut
をお読みください) 。
initramfs
は最小限の Linux 環境を提供するもので、実際のルートファイルシステムをマウントするまでの間に、プログラムを実行する仕組みを提供します。この最小限の Linux 環境は BIOS や UEFI のルーチンからメモリ内に読み込まれ、メモリ以外には特定のハードウエア要件を持ちません。また、 initramfs
には init
と呼ばれる実行ファイルが存在していなければなりません。このプログラムはルートファイルシステムの systemd
デーモンを読み込んで、続きの起動処理を実行させる役割を持ちます。
ルートファイルシステムがマウントできるようになり、オペレーティングシステムが開始できるようになるには、カーネルはルートファイルシステムの存在するデバイスにアクセスするためのドライバを読み込む必要があります。これらのドライバは特殊なハードディスク向けのドライバであったり、ネットワーク経由でアクセスする場合はネットワークドライバであったりする場合もあります。ルートファイルシステムに対して必要なモジュールは、 initramfs
内にある init
が読み込みます。必要なモジュールが読み込まれると、 udev
が initramfs
に対して必要なデバイスを提供するようになります。その後ルートファイルシステムの切り替えが行われ、再度デバイスの生成が行われます。これは systemd
のユニットである systemd-udev-trigger.service
が行います。
initramfs
にはドライバが含まれているため、新しいバージョンのドライバが提供されるようになった場合は、 initramfs
を更新する必要があります。なお、ドライバ更新を含むパッケージをインストールした場合には自動で実行されますし、 YaST や zypper でそれらのパッケージをインストールした場合は、 initramfs
を生成したことを表す出力を表示します。しかしながら、場合によっては initramfs
を手作業で生成しなければならなくなる場合があります:
ハードウエア (例: ハードディスク) の変更を行った場合で、変更したハードウエアが起動時に必要であり、かつ従来とは異なるドライバを必要とする場合は、 initramfs
ファイルの更新が必要になります。
/etc/dracut.conf.d/10-ドライバ.conf
ファイルを開くか新規に作成して、下記の行を追加します (最初の引用符の後にスペースが含まれていることに注意してください):
force_drivers+=" ドライバ_1 "
ドライバ_1 の箇所はドライバのモジュール名に置き換えてお使いください。なお、複数のドライバが必要な場合は、スペース区切りで指定します:
force_drivers+=" ドライバ_1 ドライバ_2 "
あとは 手順9.1「initramfs の生成」 の手順に従って進めます。
スワップファイルや /usr
などのシステムディレクトリを、 RAID や論理ボリュームに移動した場合も、 initramfs
を再生成して、ソフトウエア RAID や LVM のドライバが含まれるようにする必要があります。
この場合は、 /etc/fstab
内に対応する項目を作成して、その項目をマウント (例: mount -a
または swapon -a
) してください。
あとは 手順9.1「initramfs の生成」 の手順に従って進めます。
ルートファイルシステムを含む論理ボリュームグループや btrfs の RAID に対して、ディスクを追加 (または削除) した場合も、サイズの変更したボリュームにアクセスすることができるようにするため、 initramfs
を再生成する必要があります。この場合は 手順9.1「initramfs の生成」 にある手順に従ってください。
あとは 手順9.1「initramfs の生成」 の手順に従って進めます。
/etc/sysctl.conf
や /etc/sysctl.d/*.conf
などのファイルを利用して、 sysctl
インターフェイスを介してカーネルの変数を変更した場合、この変更は次回の再起動で失われてしまいます。これは実行中に sysctl --system
で変数を指定していても同様で、これらは initramfs
ファイル内に保存が行われません。この場合も 手順9.1「initramfs の生成」 に示されている手順を実行する必要があります。
スワップデバイスの追加や削除のほか、異なる UUID で再作成を行った場合は、 手順9.1「initramfs の生成」 にある手順に従って initramfs を更新する必要があります。また、 /etc/default/grub
内の GRUB_CMDLINE_*
変数についても、 resume=
以下にスワップデバイスの UUID が書かれていますので、こちらについても修正を行い、 12.2.1項 「/boot/grub2/grub.cfg
ファイル」 に書かれた手順に従って /boot/grub2/grub.cfg
を作り直してください。
なお、下記の手順では、いずれも root
による実行が必要となります。
まずは /boot
ディレクトリに移動します:
#
cd /boot
dracut
コマンドを実行して、新しい initramfs
ファイルを生成します。このとき、 出力先ファイル名 には出力先のファイル名を指定します:
#
dracut 出力先ファイル名
dracut -f
出力先ファイル名 のように実行してもかまいません。この場合は、既存のファイルを上書きします。
(この手順は、以前の手順で dracut -f
を実行した場合には不要です) 以前の手順で生成した initramfs
ファイルから、 initrd
に対してシンボリックリンクを作成します:
#
ln -sf 出力先ファイル名initrd
systemd
(initramfs
内では init
とも呼びます。詳しくは 9.1項 「用語説明」 をお読みください) を含む initramfs
がカーネルによってマウントされ、一時的なルートファイルシステムになります。このプログラムは適切なルートファイルシステムをマウントするのに必要な、全ての処理を実施するほか、必要なファイルシステム向けの機能や、 udev
によるマスストレージコントローラ向けのデバイスドライバの読み込みなどを行います。
initramfs
における init
の主な目的は、実際のルートファイルシステムのマウントを準備し、アクセスすることにあります。システムの設定によっても異なりますが、 initramfs
における init
は、下記を実施します:
ハードウエア設定にも依存しますが、お使いのコンピュータのハードウエアコンポーネント (ハードディスクなどの最も重要なもの) に対して、特別なドライバが必要となる場合があります。最終的なルートファイルシステムにアクセスするため、カーネルは適切なファイルシステムドライバも読み込む必要があります。
カーネルは読み込んだモジュールに従って、デバイスイベントを生成します。 udev
はそれらのイベントを処理して、 RAM ファイルシステムである /dev
内に、必要なブロックスペシャルファイルを作成します。これらのスペシャルファイルが存在しないと、ファイルシステムやその他のデバイスにアクセスすることができなくなります。
RAID や LVM の中にルートファイルシステムを保持するような設定を行っている場合、 initramfs
内の init
は、 LVM や RAID を設定して後続の手順でルートファイルシステムにアクセスできるように構成します。
お使いのシステムのルートファイルシステムが、ネットワーク経由でマウントするもの (例: NFS) であった場合、 init
は必要なネットワークドライバを読み込んで、ルートファイルシステムにアクセスできる状態にする必要があります。
iSCSI や SAN のようなネットワークブロックデバイス内にファイルシステムが存在する場合も、 initramfs
内の init
がネットワークを設定します。 openSUSE Leap では、プライマリ (最初) のターゲットにアクセスできない場合、セカンダリ (第 2) の iSCSI ターゲットから起動する機能に対応しています。
起動環境内でのルートファイルシステムのマウントが失敗した場合は、起動を続行するためにそれらを確認したり修復したりする必要があります。 ext3 や ext4 のファイルシステムである場合は、ファイルシステムチェッカーが自動で起動します。 XFS や btrfs のファイルシステムの場合は、修復処理が自動化されていませんので、指定可能なオプションを利用して手作業で修復作業を行います。修復が成功すると、起動環境はシステムに対してマウントのやり直しを指示します。これで問題なくマウントできれば、起動処理はそのまま続行されます。
initramfs
内の init
がインストール処理内の一部として起動時に呼び出された場合、上述とは異なる方式で処理が進みます。インストールシステムでは initramfs
から systemd
を開始することはせず、代わりに linuxrc
がこれらの処理を行います。
インストール処理を開始すると、お使いのマシンはインストール用のカーネルと、 YaST インストーラを含む特別な init
を読み込みます。 YaST インストーラは RAM 内のファイルシステムで動作するもので、オペレーティングシステムのインストールを行うためのインストールメディアの場所に関する情報を与える必要があります。
9.2.2.1項 「initramfs
ファイル」 でも説明しているとおり、起動処理はほとんどのハードウエア設定で使用できる最小セットのドライバで開始されます。 AArch64, POWER, AMD64/Intel 64 の各マシンでは、 linuxrc
が初期のハードウエア検出処理を行い、お使いのハードウエア設定でどのようなドライバが必要なのかを判別します。 IBM Z では、 linuxrc や parmfile などで、ドライバとパラメータの一覧を指定する必要があります。
これらのドライバは、システムを起動するのに必要な独自の initramfs
を生成するために使用されることになります。なお、起動時にはモジュールを必要としないコールドプラグ型のハードウエアの場合は、それらのモジュールは systemd
側で読み込みます。詳しくは 10.6.4項 「カーネルモジュールの読み込み」 をお読みください。
ハードウエアが正しく認識されると、必要なドライバが読み込まれます。 udev
プログラムは特殊なデバイスファイルを作成し、 YaST インストーラを含む linuxrc
を開始します。
最後に linuxrc
が YaST を起動します。これでパッケージのインストールやシステムの設定などを行うことができるようになります。
「実際の」 ルートファイルシステムが見つかると、まずはエラーがないかどうかを確認して、マウントを行います。マウントが成功すれば、 initramfs
がメモリ内から削除され、ルートファイルシステム内の systemd
デーモンを起動します。 systemd
は Linux システムとサービスのマネージャです。また、プロセス ID (PID) 1 で起動される親プロセスでもあり、ユーザスペースのサービスを立ち上げて管理するための init システムとしても動作します。詳しくは 第10章 「systemd
デーモン」 をお読みください。