Linuxの起動の流れ入門 - BIOS/UEFIからログインまで
この記事で解決できること
- 電源投入から login プロンプトまで、何がどの順で動くか を 1 本の線で追える
- 起動が止まったとき「どの段階で詰まったか」を切り分ける軸が手に入る
systemd-analyze/journalctl -bで 自分のマシンの起動 を観察できる
結論(起動の 5 段階)
- ファームウェア(BIOS / UEFI) … ハードを初期化し、起動デバイスを探す
- ブートローダ(GRUB) … カーネルと initramfs をメモリに読み込む
- カーネル … ハードを掌握し initramfs を一時的な root として展開
- init(systemd, PID 1) … 本物の root に切替え、サービスを並行起動
- ログイン … getty / display manager がプロンプトを出す
前提(対象環境)
- 一般的な x86_64 Linux(UEFI + GRUB 2 + systemd 構成)
- BIOS 専用機・他のブートローダ(systemd-boot 等)・他の init(OpenRC 等)では一部の名称が変わる
Linux の起動は何段階あるのか?
結論: 大きく「ファームウェア → ブートローダ → カーネル → init → ログイン」の 5 段階。各段階は次の 1 段だけを起動する責務の連鎖であり、止まった位置を特定すれば原因の範囲が一気に狭まる。
起動(boot)は魔法ではなく、バトンを渡すリレー だ。電源が入った瞬間は CPU しか信用できる状態がなく、そこから少しずつ「信用できる範囲」を広げていく。各段階は次の段階をメモリに載せて制御を渡し、自分の役目を終える。
電源ON │ ▼ ① ファームウェア(BIOS / UEFI) ハード初期化・起動デバイス選択 ▼ ② ブートローダ(GRUB) kernel + initramfs をロード ▼ ③ カーネル デバイス掌握・initramfs 展開 ▼ ④ init(systemd / PID 1) サービス起動・ターゲット到達 ▼ ⑤ ログイン(getty / DM) プロンプト表示 ユーザー操作可能
この「どこまで進んだか」が、トラブル切り分けの最重要情報になる。画面に GRUB メニューが出れば①②は成功、カーネルのメッセージが流れれば③に到達、と 見える症状で段階を逆算 できる。
① BIOS と UEFI は何をするのか?
結論: ファームウェア(BIOS / UEFI)はハードウェアを初期化し、起動可能なデバイスを探して最初のプログラムをメモリに読み込む。UEFI は EFI システムパーティション上の
.efiを直接起動できる点が BIOS と異なる。
電源投入後、最初に動くのはマザーボード上の ファームウェア だ。役割は 2 つ。
- POST(Power-On Self-Test): CPU・メモリ・ストレージなど基本ハードの存在と健全性を確認する
- 起動デバイスの選択: 設定された順序でディスク・USB・ネットワークを調べ、起動可能なものを見つける
ここで BIOS と UEFI の違いが出る。
| 観点 | BIOS(レガシー) | UEFI(現行) |
|---|---|---|
| 起動方式 | MBR 先頭 446 バイトを実行 | ESP 上の .efi 実行ファイルを起動 |
| ディスク上限 | 2 TB(MBR) | 9.4 ZB(GPT) |
| セキュア起動 | なし | Secure Boot に対応 |
| 設定保持 | CMOS | NVRAM(efibootmgr で操作) |
UEFI 機では ESP(EFI System Partition) という FAT32 の小さな領域に、ブートローダの実行ファイル(例: /EFI/ubuntu/grubx64.efi)が置かれる。UEFI はそれを直接起動するため、BIOS 時代の「MBR にコードを埋め込む」手品が不要になった。
# UEFI で起動したかの確認(このディレクトリが存在すれば UEFI ブート) $ ls /sys/firmware/efi
/sys/firmware/efi が 存在すれば UEFI、無ければ BIOS(レガシー)ブート。デュアルブートやインストールトラブルでは、まずこの一点で土俵を確定させると無駄な切り分けが減る。
② ブートローダ(GRUB)の役割は?
結論: ブートローダはカーネル本体と initramfs をディスクからメモリに読み込み、起動パラメータを付けてカーネルへ制御を渡す。GRUB はメニュー表示・カーネル選択・パラメータ編集もできる。
ファームウェアが起動するのが ブートローダ で、Linux では GRUB 2 が最も一般的だ。GRUB の仕事は次の通り。
- 複数のカーネル / OS から どれを起動するか選ぶ(あの黒い選択メニュー)
- 選ばれた カーネル本体(
vmlinuz)と initramfs(initrd.img)をメモリにロード - カーネルパラメータ(cmdline) を付与してカーネルへジャンプ
設定は /boot/grub/grub.cfg に生成されるが、これは自動生成ファイルなので 直接編集しない。元になるのは /etc/default/grub とテンプレート群だ。
# 起動に使われたカーネルとパラメータを確認 $ cat /proc/cmdline
BOOT_IMAGE=/boot/vmlinuz-6.8.0-31-generic root=UUID=... ro quiet splash
root=UUID=... が「本物の root ファイルシステムはどれか」、ro が「最初は読み取り専用でマウント」を意味する。トラブル時に GRUB メニューで e を押すと、この行を その場で編集(例: quiet splash を消して single を足す)してレスキュー起動できる。
GRUB メニューが出る=①②は成功。ここから先に進まない(カーネルメッセージが出ない)場合は、カーネルや initramfs の破損、root= の指定ミスを疑う。逆に GRUB メニューすら出なければ、原因はファームウェア設定や ESP / ブートローダ自体にある。
③ カーネルと initramfs は何をしているのか?
結論: カーネルはメモリ・CPU・デバイスを掌握し、まず initramfs を一時的な root として展開する。initramfs には本物の root をマウントするための最小限のドライバが入っており、準備ができたら本物の root へ切り替える。
GRUB から制御を受け取った カーネル(kernel) は、自身を展開してハードウェアの管理を開始する。メモリ管理・プロセススケジューラを立ち上げ、CPU の全コアを有効化し、ドライバを初期化していく。
ここで鍵になるのが initramfs(initial RAM filesystem) だ。なぜ必要か——本物の root ファイルシステムが、暗号化(LUKS)・LVM・RAID・特殊なディスクドライバの上にある場合、カーネルは「それをマウントするためのドライバ」を先に必要とする。卵が先か鶏が先かの問題だ。
initramfs はこれを解く 小さな一時 root。GRUB がカーネルと一緒にメモリへ載せたこのアーカイブを、カーネルは RAM 上に展開し、その中の init スクリプトを実行する。その役目は概ね次の通り。
- 必要なカーネルモジュール(ストレージ・暗号化等)をロード
- LVM の有効化・LUKS の復号など、本物の root を見えるようにする 準備
- 本物の root をマウントし、
switch_rootでそちらへ 根を切り替える
# カーネルが認識・初期化した過程はリングバッファに残る $ dmesg | head
initramfs の役目はここで終わり、以降は本物の root 上の /sbin/init(= systemd)が主役になる。この「一時 root → 本物の root への switch」が起動中盤の山場であり、暗号化ディスクのパスフレーズ入力もこの段階で発生する。
④ init(systemd / PID 1)は何を起動するのか?
結論: 本物の root 上で最初に起動するプロセスが init で、現在の主流は systemd(PID 1)。systemd は依存関係を解決しながらサービス(ユニット)を並行起動し、目標状態(ターゲット)への到達を目指す。
switch_root の後、カーネルが本物の root から起動する最初のユーザープロセスが PID 1 の init だ。現代の多くのディストリでは systemd がこれを担う。systemd の特徴は、サービスを 依存関係グラフ として捉え、依存のないものを 並行起動 する点にある(旧来の SysVinit が起動スクリプトを直列実行していたのと対照的)。
systemd が管理する起動単位を ユニット(unit) と呼ぶ。
*.service… デーモン / プログラム(例:sshd.service)*.mount… ファイルシステムのマウント*.socket… ソケットの待ち受け*.target… 複数ユニットをまとめた 到達目標(旧ランレベルに相当)
起動のゴールは 既定ターゲット への到達だ。サーバなら multi-user.target(CUI)、デスクトップなら graphical.target(GUI)が一般的。
# 既定ターゲットの確認(旧ランレベルの後継) $ systemctl get-default
graphical.target
| 旧ランレベル | systemd ターゲット | 意味 |
|---|---|---|
| 0 | poweroff.target |
シャットダウン |
| 1 | rescue.target |
シングルユーザー(復旧) |
| 3 | multi-user.target |
CUI マルチユーザー |
| 5 | graphical.target |
GUI |
| 6 | reboot.target |
再起動 |
systemd は default.target から依存を辿り、必要なユニットを起動していく。失敗したユニットがあっても他は進むため、「起動はしたが特定サービスだけ落ちている」という切り分けが可能になる。
systemd は各サービスを signal で制御する。停止要求は SIGTERM、応答しなければ SIGKILL という流れは、graceful shutdown の理屈そのもの。詳しくは signal(シグナル)とは を参照。
⑤ ログインプロンプトはどこから出るのか?
結論: ターゲット到達の最終段で、CUI なら getty が仮想端末に login プロンプトを、GUI なら display manager(gdm 等)がログイン画面を表示する。ここまで来れば起動は完了。
ターゲットの到達に伴い、ユーザーが操作する入口が用意される。
- CUI(
multi-user.target):getty(agetty)が各仮想端末(tty1 等)でlogin:プロンプトを表示する。Ctrl+Alt+F2などで切り替わる素のテキスト端末がこれ。 - GUI(
graphical.target): display manager(gdm/sddm/lightdm等)がグラフィカルなログイン画面を出し、認証後にデスクトップセッションを起動する。
認証は PAM(Pluggable Authentication Modules) が担い、成功するとシェル(CUI)またはデスクトップ環境(GUI)が起動して、ようやく「使える状態」になる。ここが起動リレーのゴールテープだ。
自分のマシンの起動を観察するには?
結論:
systemd-analyzeで総所要時間と遅いユニットを、journalctl -bで今回ブートの全ログを確認できる。「遅い」「特定サービスが起動しない」は、この 2 つでほぼ切り分けられる。
理屈を自分の環境で確かめる。systemd は起動の各段階を計測・記録しているので、可視化は簡単だ。
# 起動全体の所要時間(ファームウェア → カーネル → ユーザー空間) $ systemd-analyze
Startup finished in 4.123s (firmware) + 2.001s (loader) + 1.892s (kernel) + 6.540s (userspace) = 14.557s
firmware / loader / kernel / userspace の内訳が、まさに本記事の①〜④に対応している。どこが遅いかが一目で分かる。
# 起動を遅くしているユニットを上から順に $ systemd-analyze blame
# 今回のブートのログだけを読む(-b = current boot) $ journalctl -b
systemd-analyze blame の数字は 並行起動 のため単純な合計にはならない(同時に動いた分は重複計上される)。順序依存の遅延は systemd-analyze critical-chain の方が実態に近い。
まとめ:起動段階と切り分けの早見表
結論: 「画面に何が出たか」で到達段階が分かる。GRUB メニュー=①②成功、カーネルログ=③到達、emergency プロンプト=④で root マウント失敗、login=完走。症状を段階に翻訳できれば原因の範囲が定まる。
| 段階 | 担当 | 成功の見え方 | 詰まったときの主因 |
|---|---|---|---|
| ① ファームウェア | BIOS / UEFI | メーカーロゴ | 起動順序・ESP・ハード故障 |
| ② ブートローダ | GRUB | GRUB メニュー | grub.cfg・カーネル/initrd 破損 |
| ③ カーネル | kernel + initramfs | カーネルログが流れる | ドライバ欠如・root= 誤り |
| ④ init | systemd (PID 1) | サービス起動メッセージ | root マウント失敗・ユニット異常 |
| ⑤ ログイン | getty / DM | login プロンプト | DM 設定・PAM・GPU ドライバ |
起動の流れを 5 段階の責務として持っておくと、「起動しない」という漠然とした事象を どの段階の問題か に翻訳できる。あとは該当段階のログ(dmesg / journalctl -b)を読めば、原因にまっすぐ近づける。