
Linux の起動プロセスは複数の段階から成り、多くの点で、派生元であるBSDやその他のUnixスタイルの起動プロセスと似ています。Linux の起動プロセスはコンピュータのアーキテクチャに大きく依存しますが、これらのアーキテクチャは、システム起動、ブートローダー実行、Linux カーネルイメージのロードと起動、さまざまな起動スクリプトとデーモンの実行など、同様の段階とソフトウェアコンポーネントを共有しています。[ 1 ]これらは、システム起動、ブートローダー段階、カーネル段階、および init プロセスの 4 つのステップにグループ化されています。[ 3 ]
Linux システムの電源投入またはリセット時に、プロセッサは、電源投入時の自己診断テストなどのシステム初期化用の特定のファームウェア/プログラムを実行し、リセットベクタを呼び出してフラッシュ/ROM (組み込み Linux デバイスの場合) の既知のアドレスでプログラムを開始し、ブートローダーを RAM にロードして後で実行します。[ 2 ] IBM PC 互換パーソナルコンピュータ(PC)では、このファームウェア/プログラムはBIOSまたはUEFIモニタであり、マザーボードに格納されています。[ 2 ]組み込み Linux システムでは、このファームウェア/プログラムはブート ROMと呼ばれます。[ 4 ] [ 5 ] RAM にロードされた後、ブートローダー (第 1 段階ブートローダーまたはプライマリブートローダーとも呼ばれる) が実行され、第 2 段階ブートローダー[ 2 ] (セカンダリブートローダーとも呼ばれる) をロードします。[ 6 ]第 2 段階ブートローダーは、カーネルイメージをメモリにロードし、解凍および初期化してから、このカーネルイメージに制御を渡します。[ 2 ]第 2 段階のブートローダーは、システム ハードウェア チェック、ルート デバイスのマウント、必要なカーネル モジュールのロードなど、システム上でいくつかの操作を実行します。[ 2 ]最後に、最初のユーザー スペース プロセス (initプロセス) が起動し、その他の高レベルのシステム初期化 (起動スクリプトに関連するもの) が実行されます。[ 2 ]
これらの各ステージとコンポーネントには、さまざまなバリエーションとアプローチがあります。たとえば、ブートローダーとしてGRUB、systemd-boot、coreboot 、またはDas U-Bootを使用できます (歴史的な例としてはLILO、SYSLINUX 、またはLoadlinがあります)。一方、起動スクリプトは従来のinitスタイルにすることも、 systemdやrunitなどの最新の代替手段を使用してシステム構成を実行することもできます。
システム起動の手順は、Linuxが起動されるハードウェアによって異なります。[ 7 ]
IBM PC互換ハードウェアは、Linuxが一般的に使用されるアーキテクチャの一つであり、これらのシステムではBIOSまたはUEFIファームウェアが重要な役割を果たします。
BIOS システムでは、BIOS は、システム ハードウェアをチェックする電源投入時自己診断テスト (POST) を順に実行し、次にローカル デバイスを列挙し、最後にシステムを初期化します。[ 7 ]システムの初期化では、BIOS は、OS を格納するシステム上の起動可能なデバイスを検索することから始めます。起動可能なデバイスには、フロッピー ディスク、CD-ROM、USB フラッシュ ドライブ、ハードディスクのパーティション (ハードディスクに複数の OS (Windows と Fedora など) が格納されている場合)、ローカル ネットワーク上のストレージ デバイスなどがあります。[ 7 ] Linux を起動するハードディスクには、RAM にロードされる第 1 段階 / プライマリ ブート ローダーを含むマスターブート レコード(MBR) が格納されています。 [ 7 ]
UEFI システムでは、Linux カーネルは EFI ブート スタブを介して UEFI ファームウェアによって直接実行できますが、 [ 8 ]通常はブートローダーとしてGRUB 2またはsystemd-boot を使用します。 [ 9 ] [ 10 ]
UEFI セキュア ブートがサポートされている場合、ブートローダーまたは EFI スタブを含むカーネルの前に、UEFI によって「shim」または「Preloader」が起動されることがよくあります。[ 11 ] UEFI セキュア ブートが無効になっている 場合でも、後で有効になる場合に備えて、これが存在して起動されることがあります。これは、UEFI キー データベースを変更することなく、後続のブート ステージの署名検証用のキーを提供する追加の署名キー データベースを追加するだけであり、UEFI が行うのと同様に後続のブート ステップに連鎖します。
組み込みLinuxシステムのシステム起動ステージは、オンチップブートROM上のファームウェア/プログラムの実行から始まり、eMMC、eUFS、NANDフラッシュなどのストレージデバイスからブートローダー/オペレーティングシステムをロードします。[ 5 ]システム起動のシーケンスはプロセッサによって異なりますが[ 5 ]、すべてハードウェア初期化とシステムハードウェアテストのステップが含まれています。[ 7 ]例えば、i.MX7DプロセッサとOS(U-Bootを含む)を格納するブート可能なデバイスを備えたシステムでは、オンチップブートROMは最初にDDRメモリコントローラを設定し、ブートROMのプログラムがブート可能なデバイス上の外部ブートローダーからSoC構成データを取得できるようにします。[ 5 ]次に、オンチップブートROMはブートローダーステージのためにU-BootをDRAMにロードします。[ 12 ]
BIOSを使用するIBM PC 互換機では、マスター ブート レコード(MBR)の一部である第 1 ステージ ブート ローダーは、ベンダー固有のプログラム コードとパーティション テーブルを含む 512 バイトのイメージです。[ 6 ]導入部分で前述したように、第 1 ステージ ブート ローダーは第 2 ステージ ブート ローダーを見つけてロードします。[ 6 ]これは、パーティション テーブルでアクティブなパーティションを検索することによって行われます。[ 6 ]アクティブなパーティションが見つかると、第 1 ステージ ブート ローダーはテーブル内の残りのパーティションをスキャンし続け、すべてが非アクティブであることを確認します。[ 6 ]このステップの後、アクティブなパーティションのブート レコードが RAM に読み込まれ、第 2 ステージ ブート ローダーとして実行されます。[ 6 ]第 2 ステージ ブート ローダーの役割は、Linux カーネル イメージをメモリとオプションの初期 RAM ディスクにロードすることです。[ 13 ]カーネル イメージは実行可能なカーネルではなく、zlibを使用してzImage または bzImage形式に圧縮されたカーネルの「圧縮ファイル」です。[ 14 ]
これらのシステムでは、第 1 段階および第 2 段階のブートローダーは通常GRand Unified Bootloader (GRUB) によって提供され、以前は Linux Loader ( LILO ) によって提供されていました。[ 13 ]現在使用されているGRUB 2は、さまざまなオペレーティングシステムの自動検出と自動構成が可能である点で GRUB 1 とは異なります。stage1 は、BIOS によって MBR からロードされ実行されます。中間ステージ ローダー (stage1.5、通常は core.img) は、stage1 ローダーによってロードされ実行されます。第 2 段階ローダー (stage2、/boot/grub/ ファイル) は stage1.5 によってロードされ、ユーザーがオペレーティングシステムを選択したり、起動パラメータを調べて編集したりできる GRUB 起動メニューを表示します。メニュー項目が選択され、オプションのパラメータが指定されると、GRUB は Linux カーネルをメモリにロードし、制御をカーネルに渡します。GRUB 2 は、別のブートローダーをチェーン ロードすることもできます。
UEFIシステムでは、stage1とstage1.5は通常、同じUEFIアプリケーションファイルです(例えば、x64 UEFIシステムの場合はgrubx64.efi)。
GRUB以外にも、人気のあるブートローダーがいくつかあります。
現在ではあまり使われなくなった、過去のブートローダーには以下のようなものがある。
/etc/lilo.confカーネルと RAM ディスク (initrd または initramfs) の位置に関する生のオフセット情報 (マッパー ツール) をマッピングする構成ファイル ( ) がライブ システムで作成されます。ブートパーティションやカーネルパス名などのデータ、必要に応じてカスタマイズされたオプションを含む構成ファイルは、ブートローダー コードとともに MBR ブートセクタに書き込まれます。このブートセクタが BIOS によって読み込まれて制御されると、LILO はメニュー コードをロードして描画し、保存された値とユーザー入力を使用して Linux カーネルを計算してロードするか、他のブートローダーをチェーン ロードします。カーネルステージはブートローダーステージの後に発生します。Linuxカーネルは、メモリ管理、タスクスケジューリング、I/O、プロセス間通信、システム全体の制御など、すべてのオペレーティングシステムプロセスを処理します。これは2つのステージでロードされます。最初のステージでは、カーネル(圧縮イメージファイルとして)がメモリにロードされ、解凍され、基本的なメモリ管理や最小限のハードウェア設定などのいくつかの基本機能が設定されます。[ 14 ]カーネルイメージは自己解凍され、これはカーネルイメージのルーチンの一部です。[ 14 ]一部のプラットフォーム(ARM 64ビットなど)では、カーネルの解凍はU-Bootなどのブートローダーによって実行する必要があります。[ 17 ]
これらの手順の詳細については、 i386マイクロプロセッサの例を見てみましょう。bzImage が呼び出されると、start()( の./arch/i386/boot/head.S) 関数が呼び出されて基本的なハードウェア設定を行い、startup_32()( にある./arch/i386/boot/compressed/head.S) を呼び出します。[ 14 ]startup_32()は環境 (スタックなど) の基本的な設定を行い、シンボルによって開始されるブロック(BSS) をクリアしてから、decompress_kernel()( にある./arch/i386/boot/compressed/misc.c) を呼び出してカーネルを解凍します。[ 14 ]startup_32()カーネルの起動は、にある別の関数を介して実行されます./arch/i386/kernel/head.S。[ 14 ]startup_32()カーネルの起動関数(スワッパーまたはプロセス 0 とも呼ばれます) は、メモリ管理(ページング テーブルとメモリ ページング) を確立し、 CPUの種類と浮動小数点機能などの追加機能を検出し、start_kernel()にあるの呼び出しを介してアーキテクチャ固有ではない Linux カーネル機能に切り替えます./init/main.c。[ 14 ]
start_kernel()は、さまざまな初期化機能を実行します。割り込み処理( IRQ ) を設定し、メモリをさらに構成し、ブートローダー段階で一時ルートファイルシステムとして以前にロードされた初期 RAM ディスク("initrd") をマウントします。 [ 14 ] RAM 内の一時ルートファイルシステムとして機能する initrd により、カーネルを完全に起動し、他のデバイス (ハードディスクなど) に依存することなく、ドライバ モジュールをメモリから直接ロードできます。[ 14 ] initrd には通常、ストレージ周辺機器とインターフェースするために必要なモジュール( SATA ドライバなど) が含まれており、多数のハードウェア構成をサポートします。[ 14 ]一部のドライバをカーネルに静的にコンパイルし、他のドライバを initrd からロードするというこの分割により、カーネルを小さくすることができます。[ 14 ] initramfs(早期ユーザー空間とも呼ばれる)は、Linuxカーネルのバージョン2.5.46以降で利用可能になっており、[ 18 ]以前はカーネルが起動プロセス中に実行していた機能を可能な限り置き換えることを目的としています。早期ユーザー空間の典型的な用途は、メインのユーザー空間ファイルシステムをロードするために必要なデバイスドライバを検出し、一時ファイルシステムからロードすることです。多くのディストリビューションでは、dracutを使用してinitramfsイメージを生成および維持しています。
ルートファイルシステムは、pivot_root()一時的なルートファイルシステムをアンマウントし、アクセス可能になった実際のルートファイルシステムに置き換える呼び出しによって、後で切り替えられます。[ 14 ]その後、一時的なルートファイルシステムによって使用されていたメモリが解放されます。
最後に、kernel_thread(in arch/i386/kernel/process.c)が呼び出されてInitプロセス(最初のユーザー空間プロセス)が開始され、その後、を介してアイドルタスクが開始されますcpu_idle()。[ 14 ]
このように、カーネルステージではデバイスを初期化し、ブートローダーで指定されたルートファイルシステムを読み取り専用としてマウントし、システムによって最初に実行されるプロセス ( PID = 1) として指定されるInit ( ) を実行します。[ 19 ]カーネルはファイルシステムをマウントするとメッセージを出力し、Init は Init プロセスを開始するとメッセージを出力します。[ 19 ]/sbin/init
Red Hatによると、この段階での詳細なカーネルプロセスは次のように要約されます。[ 15 ]
この時点で、割り込みが有効になっているため、スケジューラはシステム全体の管理を制御できるようになり、プリエンプティブなマルチタスク処理を提供できます。一方、initプロセスはユーザー空間でユーザー環境の起動を継続します。
カーネルが起動すると、initプロセス[ 20 ]というデーモンが起動し、ファイルシステムのチェックやマウントなどによってユーザー空間をブートストラップし、他のプロセスを起動します。initシステムは、起動時に最初に起動するデーモンであり、シャットダウン時に最後に終了するデーモンです。
歴史的にはこれは「SysV init」と呼ばれ、単に「init」と呼ばれていました。最近のLinuxディストリビューションでは、systemdなどのより現代的な代替手段が使用されることが多いでしょう。以下に、主要なinitプロセスの概要を示します。
"/etc/rc..."があり、ブート プロセスで必要に応じて参照されるのはこれらのスクリプトです。init スクリプトは通常、などのディレクトリに格納されます。init の最上位設定ファイルはにあります/etc/inittab。[ 21 ]システム ブート中、/etc/inittab にデフォルトのランレベルが指定されているかどうかを確認し、指定されていない場合はシステム コンソール経由でランレベルに入るよう要求します。次に、モジュールのロード、ルートファイルシステム (読み取り専用でマウントされていた) の整合性のチェック、完全な読み書きアクセス用に再マウント、ネットワークの設定など、指定されたランレベルに関連するすべてのブート スクリプトを実行します。[ 19 ]指定されたすべてのプロセスを生成した後、init は休止状態になり、開始したプロセスが終了または停止する、電源障害シグナル、または実行レベルをさらに変更するための要求のいずれかが発生するのを待ちます/sbin/telinit。[ 22 ]