Linux のブートおよびスタートアップ プロセスの紹介

Linux のブートおよびスタートアップ プロセスを理解することは、Linux の設定とスタートアップ問題の解決の両方ができるようになるために重要です。 この記事では、GRUB2 ブートローダーを使用した起動シーケンスと、systemd 初期化システムによって実行される起動シーケンスの概要を説明します。

実際には、Linux コンピューターを起動して使用可能にするために必要なイベントのシーケンスは、起動と開始の 2 つです。 ブートシークエンスはコンピュータの電源を入れたときに始まり、カーネルが初期化され、systemd が起動したときに完了します。

全体として、Linux のブートおよびスタートアップ プロセスは、理解するのがかなり簡単です。

  • BIOS POST
  • ブート ローダー (GRUB2)
  • カーネル初期化
  • すべてのプロセスの親である systemd を開始する

この記事では GRUB2 と systemd を取り上げますが、それはこれらが現在のほとんどの主要ディストリビューションのブート ローダーおよび初期化ソフトウェアであることに注意してください。

ブートプロセス

ブートプロセスは、いくつかの方法のうちのひとつで開始することができます。 まず、電源がオフになっている場合、電源をオンにするとブート プロセスが開始されます。 コンピューターがすでに root または非特権ユーザーを含むローカル ユーザーを実行している場合、ユーザーは GUI またはコマンドラインを使用して再起動を開始することにより、プログラム的に起動シーケンスを開始することができます。

BIOS POST

Linux ブート プロセスの最初のステップは、Linux とは何の関係もありません。 これは、ブート プロセスのハードウェア部分で、どのオペレーティング システムでも同じです。

1981年に IBM が最初の PC を設計したとき、BIOS はハードウェア コンポーネントを初期化するように設計されていました。

1981年にIBMが最初のPCを設計したとき、BIOSはハードウェアのコンポーネントを初期化するように設計されました。

BIOSのPOSTは、ハードウェアの基本的な操作性をチェックし、BIOS割り込み(INT 13H)を発行して、接続されているすべてのブータブル デバイス上のブート セクターを探します。 有効なブート レコードを含む最初に見つかったブート セクターが RAM にロードされ、ブート セクターからロードされたコードに制御が移行します。 ほとんどの Linux ディストリビューションで使用されるブート ローダーには、GRUB、GRUB2、および LILO の 3 つがあります。

GRUB2

GRUB2は「GRand Unified Bootloader, version 2」の略で、現在のほとんどの Linux ディストリビューションで主要なブート ローダーになっています。 GRUB2 は、オペレーティング システム カーネルを見つけ、それをメモリにロードするために、コンピューターを十分に賢くするためのプログラムです。

GRUBはマルチブート仕様と互換性があるように設計されており、GRUBは多くのバージョンのLinuxや他の自由なオペレーティング システムを起動することができます。 これは、更新されたカーネルが何らかの理由で失敗したり、重要なソフトウェアと互換性がない場合、以前のバージョンのカーネルを起動する能力を提供します。 GRUB は /boot/grub/grub.conf ファイルを使用して設定できます。

GRUB1は現在レガシーとみなされ、ほとんどの最新ディストリビューションでは、GRUB1 を書き直した GRUB2 で置き換えられています。 Red Hat ベースのディストロは、Fedora 15 と CentOS/RHEL 7 のあたりで GRUB2 にアップグレードしました。 GRUB2はGRUB1と同じブート機能を提供しますが、GRUB2はメインフレームのようなコマンドベースのプリOS環境でもあり、プリブートの段階でより柔軟な対応が可能になっています。 GRUB2 は /boot/grub2/grub.cfg で設定します。

どちらの GRUB も、主な機能は Linux カーネルをメモリにロードして実行させることです。 GRUB の両方のバージョンは基本的に同じように動作し、同じ 3 つのステージがありますが、GRUB がどのように仕事をするかについてのこの議論では、GRUB2 を使用することにします。 GRUB または GRUB2 の設定と GRUB2 コマンドの使用はこの記事の範囲外です。

GRUB2 は公式に GRUB2 の 3 つのステージにステージ表記を使用していませんが、そのように参照すると便利なので、この記事で使用することにします。

ステージ 1

BIOS POST セクションで述べたように、POST の終わりに、BIOS は接続されたディスクを検索して、通常は Master Boot Record (MBR) にあるブート レコードを探し、最初に見つかったものをメモリにロードして、それからブート レコードの実行を開始します。 ブートストラップコード、すなわちGRUB2ステージ1は、パーティションテーブルとともにハードディスク上の最初の512バイトのセクタに収まる必要があるため、非常に小さいものとなっている。 古典的な汎用MBRで実際のブートストラップコードに割り当てられるスペースの総量は446バイトです。 ステージ 1 の 446 バイトのファイルは boot.img という名前で、別途ブート レコードに追加されるパーティション テーブルは含まれません。

ブート レコードは非常に小さい必要があるので、あまり賢くなく、ファイルシステム構造を理解しません。 したがって、ステージ 1 の唯一の目的は、ステージ 1.5 の場所を特定し、ロードすることです。 これを達成するために、GRUBのステージ1.5はブートレコード自体とドライブの最初のパーティションの間のスペースに配置する必要があります。 GRUB ステージ 1.5 を RAM にロードした後、ステージ 1 はステージ 1.5 に制御を移します。

ステージ 1.5

前述のように、GRUB のステージ 1.5 はブート レコード自体とディスク ドライブの最初のパーティションの間のスペースに配置する必要があります。 このスペースは、技術的な理由により、歴史的に未使用のままでした。 ハードディスクの最初のパーティションはセクター 63 から始まり、セクター 0 に MBR があるため、62 の 512 バイト セクター (31,744 バイト) が GRUB のステージ 1.5 である core.img ファイルを格納するために残されています。

ステージ 1.5 に収容できるコードの量が多いので、標準の EXT やその他の Linux ファイルシステム、FAT、NTFS など、いくつかの一般的なファイルシステム ドライバーを収容するのに十分なコードを持つことができます。 GRUB2 core.img は、古い GRUB1 stage 1.5 よりもはるかに複雑で高機能です。 つまり、GRUB2のステージ2は標準的なEXTファイルシステムに配置することはできますが、論理ボリュームに配置することはできません。 したがって、ステージ 2 ファイルの標準的な場所は、/boot ファイルシステム、特に /boot/grub2 です。

/bootディレクトリは、GRUB がサポートするファイルシステム上に配置されなければならないことに注意してください。 すべてのファイルシステムがサポートされているわけではありません。

ステージ 1.5 の機能は、/boot ファイルシステムでステージ 2 のファイルを見つけ、必要なドライバーをロードするために必要なファイルシステムドライバーで実行を開始することです。

ステージ 2

GRUB ステージ 2 のすべてのファイルは /boot/grub2 ディレクトリといくつかのサブディレクトリに配置されています。 GRUB2 はステージ 1 やステージ 2 のようなイメージ ファイルを持ちません。

GRUB2 ステージ 2 の機能は、Linux カーネルを検索して RAM にロードし、コンピューターの制御をカーネルに委ねることです。 カーネルとその関連ファイルは、/boot ディレクトリにあります。 カーネルファイルは、すべてvmlinuzで始まる名前なので、識別可能です。

GRUB2 は、GRUB1 と同様に、選択した Linux カーネルの 1 つからの起動をサポートします。 Red Hat のパッケージ マネージャーである DNF は、複数のバージョンのカーネルを維持することをサポートしており、最新のカーネルで問題が発生した場合、古いバージョンのカーネルを起動することが可能です。 デフォルトでは、GRUB はインストールされたカーネルのプリブート メニューを提供し、レスキュー オプションと、設定されている場合はリカバリ オプションを含みます。

GRUB2 のステージ 2 では、選択したカーネルをメモリにロードし、コンピューターの制御をカーネルに引き継ぎます。

選択したカーネルがメモリにロードされて実行を開始した後、役に立つ作業を行う前に、まず圧縮されたバージョンのファイルから自身を抽出する必要があります。 カーネルが自身を抽出すると、古い SysV init プログラムの代替である systemd をロードし、制御をそれに引き継ぎます。

これでブート プロセスが終了しました。

これが起動プロセスの終わりです。

起動プロセス

起動プロセスは起動プロセスに続き、Linux コンピューターを生産的な作業に使用できる状態にします。

systemd

systemd はすべてのプロセスのマザーで、Linux ホストを生産的に作業できる状態にする責任があります。 その機能のいくつかは、古い init プログラムよりもはるかに広範囲で、ファイルシステムのマウントや、生産的な Linux ホストに必要なシステムサービスの開始と管理など、実行中の Linux ホストの多くの側面を管理することです。

最初に、systemd はスワップファイルやパーティションを含む /etc/fstab で定義されたファイルシステムをマウントします。 この時点で、systemd は自分自身を含む /etc にある設定ファイルにアクセスできるようになります。 設定ファイル /etc/systemd/system/default.target を使って、ホストを起動する状態 (ターゲット) を決定します。 default.target ファイルは、真のターゲットファイルへのシンボリックリンクに過ぎません。 デスクトップワークステーションでは、これは通常 graphical.target となり、古い SystemV init のランレベル 5 に相当します。 サーバーの場合、デフォルトは、SystemV のランレベル 3 に相当する multi-user.target になる可能性が高くなります。

ターゲットとサービスは systemd 単位であることに注意してください。

以下の表 1 は、systemd ターゲットと古い SystemV スタートアップのランレベルの比較です。 systemd のターゲットエイリアスは下位互換性のために systemd によって提供されています。 ターゲットエイリアスはスクリプトや私のような多くのシステム管理者が init 3 のような SystemV コマンドを使用してランレベルを変更することを可能にします。 Of course, the SystemV commands are forwarded to systemd for interpretation and execution.

SystemV Runlevel systemd target systemd target aliases Description
halt.target Halts the system without powering it down.
0 poweroff.target runlevel0.target Halts the system and turns the power off.
S emergency.target Single user mode. No services are running; filesystems are not mounted. This is the most basic level of operation with only an emergency shell running on the main console for the user to interact with the system.
1 rescue.target runlevel1.target A base system including mounting the filesystems with only the most basic services running and a rescue shell on the main console.
2 runlevel2.target Multiuser, without NFS but all other non-GUI services running.
3 multi-user.target runlevel3.target All services running but command line interface (CLI) only.
4 runlevel4.target Unused.
5 graphical.target runlevel5.target multi-user with a GUI.
6 reboot.target runlevel6.target Reboot
default.target This target is always aliased with a symbolic link to either multi-user.target or graphical.target. systemd always uses the default.target to start the system. default.target は halt.target、poweroff.target、または reboot.target のエイリアスであってはなりません。

Table 1: Systemd ターゲットといくつかのターゲットエイリアスでの SystemV ランレベルの比較。

それぞれのターゲットには構成ファイル内に記述される一連の依存関係群があり、systemd は必須の依存関係を開始します。 これらの依存関係は、特定のレベルの機能で Linux ホストを実行するために必要なサービスです。

systemd はまた、レガシー SystemV init ディレクトリを調べて、そこにスタートアップファイルが存在するかどうかを確認します。 もしあれば、systemd はそれらを設定ファイルとして使用し、そのファイルによって記述されたサービスを開始します。

以下の図 1 は bootup man ページから直接コピーしたものです。 これは、systemd のスタートアップ中のイベントの一般的なシーケンスと、スタートアップの成功を確実にするための基本的な順序付け要件を示します。

sysinit.target、および basic.target ターゲットはスタートアップ プロセスにおけるチェックポイントとして考えることができます。 systemd はシステムサービスを並行して開始することを設計目標の 1 つとしていますが、他のサービスやターゲットが開始される前に開始されなければならない特定のサービスや機能ターゲットがまだ存在します。

そのため、sysinit.target は、それに依存するすべてのユニットが完了したときに到達します。 ファイルシステムのマウント、スワップ ファイルの設定、udev の起動、ランダム ジェネレーターの種の設定、低レベル サービスの開始、および 1 つ以上のファイルシステムが暗号化されている場合の暗号サービスの設定など、これらのユニットはすべて完了する必要がありますが、sysinit.target 内ではこれらのタスクを並行して実行することができます。

local-fs-pre.target
|
v
(various mounts and (various swap (various cryptsetup
fsck services...) devices...) devices...) (various low-level (various low-level
| | | services: udevd, API VFS mounts:
v v v tmpfiles, random mqueue, configfs,
local-fs.target swap.target cryptsetup.target seed, sysctl, ...) debugfs, ...)
| | | | |
\__________________|_________________ | ___________________|____________________/
\|/
v
sysinit.target
|
____________________________________/|\________________________________________
/ | | | \
| | | | |
v v | v v
(various (various | (various rescue.service
timers...) paths...) | sockets...) |
| | | | v
v v | v rescue.target
timers.target paths.target | sockets.target
| | | |
v \_________________ | ___________________/
\|/
v
basic.target
|
____________________________________/| emergency.service
/ | | |
| | | v
v v v emergency.target
display- (various system (various system
manager.service services services)
| required for |
| graphical UIs) v
| | multi-user.target
| | |
\_________________ | _________________/
\|/
v
graphical.target

Figure 1: The systemd startup map.

sysinit.target が完了したら、systemd は次に basic.target を起動し、これを完了するために必要なすべてのユニットを起動します。 基本ターゲットは、次のターゲットに必要なユニットを起動することで、いくつかの追加機能を提供します。

最後に、ユーザーレベルのターゲットである multi-user.target または graphical.target を初期化することができます。

図 1 の下線部のターゲットは、通常のスタートアップ ターゲットです。 これらのターゲットの 1 つに到達すると、スタートアップが完了します。 multi-user.target がデフォルトである場合、コンソールにテキスト モードでのログインが表示されるはずです。 表示される特定の GUI ログイン画面は、使用するデフォルトのディスプレイ マネージャーに依存します。

問題

私は最近、GRUB2 を使用する Linux コンピューター上でデフォルトのブート カーネルを変更する必要が生じました。 いくつかのコマンドが正しく動作しない、あるいは、正しく使用されていないことがわかりました。

grub2-set-default コマンドは、/etc/default/grub ファイル内のデフォルト カーネル インデックスを正しく設定しなかったため、希望の代替カーネルがブートしませんでした。 そこで、私は手動で /etc/default/grub GRUB_DEFAULT=saved を GRUB_DEFAULT=2 (2 は私が起動したいインストール済みカーネルのインデックス) に変更しました。 そして、grub2-mkconfig > /boot/grub2/grub.cfg というコマンドを実行して、新しいgrub設定ファイルを作成したのです。 この回避策は期待どおりに機能し、代替カーネルで起動しました。

結論

GRUB2 と systemd init システムは、最近のほとんどの Linux ディストリビューションの起動フェーズにおける主要なコンポーネントです。 特に systemd を取り巻く論争があるという事実にもかかわらず、これら 2 つのコンポーネントは、最初にカーネルをロードし、次に機能的な Linux システムを生成するために必要なすべてのシステムサービスを起動するためにスムーズに連携しています。 man ページには systemd に関する多くの情報があり、freedesktop.org には systemd の man ページ一式がオンラインで公開されています。 より多くのリンクについては、以下のリソースを参照してください。