はじめに
PCの電源を入れてからログイン画面が出るまで、何が起きてるか知ってる?
FreeBSDのブートプロセスを完全に理解しよう。
ブートプロセス全体像
┌─────────────────────────────────────────────────────────────┐
│ FreeBSD Boot Process │
│ │
│ 1. BIOS/UEFI │
│ ↓ │
│ 2. Boot Manager (boot0 / UEFI Boot Manager) │
│ ↓ │
│ 3. Boot Loader (boot2 / loader.efi) │
│ ↓ │
│ 4. Kernel (kernel) │
│ ↓ │
│ 5. Init (/sbin/init) │
│ ↓ │
│ 6. rc scripts (/etc/rc.*) │
│ ↓ │
│ 7. Login (getty → login) │
└─────────────────────────────────────────────────────────────┘
1. BIOS/UEFI
BIOS(レガシー)
┌─────────────────────────────────────────────────────────────┐
│ MBR (Master Boot Record) - 512 bytes │
│ ┌────────────────────────────────────────┬──────────────┐ │
│ │ Boot Code (446 bytes) │ Part Table │ │
│ │ boot0 │ (64 bytes) │ │
│ └────────────────────────────────────────┴──────────────┘ │
│ │ 0x55AA (2)│ │
└─────────────────────────────────────────────────────────────┘
BIOSはMBRの先頭446バイトを実行する。
UEFI
EFI System Partition (ESP)
/EFI/
└── BOOT/
└── BOOTx64.efi ← UEFIが実行
/EFI/
└── FreeBSD/
└── loader.efi ← FreeBSDブートローダー
UEFIは直接EFIアプリケーション(.efi)を実行できる。
2. Boot Manager (boot0)
BIOS環境
# MBRにboot0をインストール
gpart bootcode -b /boot/boot0 ada0
boot0の画面:
F1 FreeBSD
F2 Windows
F5 Chainload Drive 1
Default: F1
複数OS選択が可能。
UEFI環境
UEFIのブートマネージャーが直接OS選択を担当。
# EFI変数を確認
efibootmgr -v
# Boot0001* FreeBSD HD(1,GPT,...)/File(\EFI\FREEBSD\LOADER.EFI)
# Boot0002* Windows HD(2,GPT,...)/File(\EFI\Microsoft\Boot\bootmgfw.efi)
3. Boot Loader
BIOS: boot2 → loader
┌─────────────────────────────────────────────────────────────┐
│ パーティションブートセクタ │
│ ┌──────────────┐ │
│ │ boot1 │ (512 bytes) UFS/ZFSを認識 │
│ └──────────────┘ │
│ ↓ │
│ ┌──────────────┐ │
│ │ boot2 │ ファイルシステムから/boot/loaderを読む │
│ └──────────────┘ │
│ ↓ │
│ ┌──────────────┐ │
│ │ loader │ フル機能のブートローダー │
│ └──────────────┘ │
└─────────────────────────────────────────────────────────────┘
UEFI: loader.efi
ls /boot/efi/EFI/FreeBSD/
# loader.efi
loaderの機能
/boot/loader.conf (press Enter for defaults)
or any other key to proceed to loader prompt:
____ ____ ____ ____ ____ ____
||F ||||r ||||e ||||e ||||B ||||S ||
||__||||__||||__||||__||||__||||D ||
|/__\||/__\||/__\||/__\||/__\||/__\|
Welcome to FreeBSD!
1. Boot Multi user [Enter]
2. Boot Single user
3. Escape to loader prompt
4. Reboot
5. Kernel: kernel (1 of 2)
Options:
6. Configure Boot Options...
loaderプロンプト
Type '?' for a list of commands, 'help' for more detailed help.
OK ?
Available commands:
autoboot bcachestat boot chain
efi-autoresectconsole echo heap
help include load lsdev
...
OK show
...
OK set kern.hz=1000
OK boot
4. カーネル起動
loader.conf
# /boot/loader.conf
kernel="kernel" # デフォルトカーネル
# kernel="kernel.old" # 古いカーネル
# モジュールの自動ロード
if_em_load="YES"
zfs_load="YES"
dtrace_load="YES"
# カーネルパラメータ
kern.hz="1000"
debug.debugger_on_panic="1"
# コンソール設定
boot_serial="YES"
comconsole_speed="115200"
カーネルの初期化フロー
┌─────────────────────────────────────────────────────────────┐
│ Kernel Initialization │
│ │
│ 1. locore.S (アセンブリ) │
│ - CPU初期化、ページテーブル設定 │
│ ↓ │
│ 2. init_main.c :: mi_startup() │
│ - SYSINIT() で登録された初期化関数を順番に実行 │
│ ↓ │
│ 3. 各サブシステム初期化 │
│ - SI_SUB_COPYRIGHT: 著作権表示 │
│ - SI_SUB_VM: 仮想メモリ │
│ - SI_SUB_KMEM: カーネルメモリアロケータ │
│ - SI_SUB_CPU: CPU │
│ - SI_SUB_DEVFS: デバイスファイルシステム │
│ - SI_SUB_DRIVERS: デバイスドライバ │
│ - SI_SUB_CONFIGURE: autoconfiguration │
│ ↓ │
│ 4. SI_SUB_RUN_SCHEDULER: スケジューラ開始 │
│ ↓ │
│ 5. create_init() → /sbin/init を exec │
└─────────────────────────────────────────────────────────────┘
起動メッセージ
FreeBSD 14.2-RELEASE #0 releng/14.2-n269506-c8918d6c7412: Fri Nov 8 11:24:11 UTC 2024
root@releng2.nyi.freebsd.org:/usr/obj/usr/src/amd64.amd64/sys/GENERIC amd64
FreeBSD clance program.
CPU: Intel(R) Xeon(R) CPU E5-2680 v4 @ 2.40GHz (2400.10-MHz K8-class CPU)
Origin="GenuineIntel" Id=0x406f1 Family=0x6 Model=0x4f Stepping=1
...
real memory = 68719476736 (65536 MB)
avail memory = 66430898176 (63353 MB)
...
Mounting from zfs:zroot/ROOT/default...
...
5. Init
カーネルが最初に起動するユーザープロセスは/sbin/init(PID 1)。
ps aux | head -2
# USER PID %CPU %MEM VSZ RSS TT STAT STARTED TIME COMMAND
# root 1 0.0 0.0 10852 1388 - ILs Dec01 0:00.06 /sbin/init
initの役割
-
/etc/rcスクリプトを実行 - シングルユーザーモードかマルチユーザーモードを判断
- マルチユーザーモードなら
/etc/ttysに従ってgettyを起動 - シグナルを監視(再起動など)
6. rc スクリプト
/etc/rc
#!/bin/sh
# $FreeBSD$
# System startup script run by init(8) on autoboot
# or after single-user.
stty status '^T'
trap : 2
trap "echo 'Boot interrupted'; exit 1" 3
HOME=/
PATH=/sbin:/bin:/usr/sbin:/usr/bin
export HOME PATH
. /etc/rc.subr
load_rc_config ''
# ... 続く
起動順序
┌─────────────────────────────────────────────────────────────┐
│ rc Script Execution │
│ │
│ /etc/rc │
│ ↓ │
│ /etc/rc.d/ (ベースシステムのスクリプト) │
│ REQUIRE/BEFORE で依存関係を解決して順番に実行 │
│ ↓ │
│ /usr/local/etc/rc.d/ (pkg でインストールされたもの) │
│ ↓ │
│ /etc/rc.local (あれば) │
└─────────────────────────────────────────────────────────────┘
rcスクリプトの例
cat /etc/rc.d/sshd
#!/bin/sh
#
# PROVIDE: sshd
# REQUIRE: LOGIN FILESYSTEMS
# KEYWORD: shutdown
#
. /etc/rc.subr
name="sshd"
rcvar="sshd_enable"
command="/usr/sbin/sshd"
keygen_cmd="sshd_keygen"
start_precmd="sshd_precmd"
reload_precmd="sshd_configtest"
restart_precmd="sshd_configtest"
...
PROVIDE/REQUIRE/BEFOREで依存関係を定義。
rcの操作
# サービス一覧
service -l
# 有効なサービス一覧
service -e
# サービス制御
service sshd start
service sshd stop
service sshd restart
service sshd status
# 自動起動設定
sysrc sshd_enable="YES"
7. Login (getty → login)
/etc/ttys
cat /etc/ttys
# name getty type status comments
#
console none unknown off secure
#
ttyv0 "/usr/libexec/getty Pc" xterm onifexists secure
ttyv1 "/usr/libexec/getty Pc" xterm onifexists secure
ttyv2 "/usr/libexec/getty Pc" xterm onifexists secure
...
ttyu0 "/usr/libexec/getty 3wire" vt100 onifconsole secure
ログインの流れ
init
↓ fork
getty (ttyv0)
↓ login: プロンプトを表示
↓ ユーザー名入力
exec login
↓ Password: プロンプトを表示
↓ 認証成功
exec shell (/bin/sh 等)
ブートの問題解決
シングルユーザーモードで起動
ブートメニューで "2. Boot Single user" を選択。
Enter full pathname of shell or RETURN for /bin/sh:
# (Enter)
# mount -u /
# mount -a
# (修復作業)
# exit
ブートローダープロンプト
OK boot -s # シングルユーザー
OK boot kernel.old # 古いカーネルで起動
OK unload # 全モジュールをアンロード
OK load kernel # カーネルをロード
OK boot # 起動
起動しない時のチェックリスト
- カーネルパニック: kernel.oldで起動
-
fsckエラー: シングルユーザーで
fsck -y - rc.confのミス: シングルユーザーで修正
- デバイスが見つからない: loader.confでモジュールをロード
まとめ
FreeBSDのブートプロセス:
- BIOS/UEFI: ハードウェア初期化
- boot0/EFI: ブートマネージャー
- loader: 柔軟なブートローダー
- kernel: OS本体
- init: 最初のプロセス
- rc: サービス起動
- getty/login: ユーザーログイン
loader.confとrc.confを理解すれば、ブートのカスタマイズは自由自在。
この記事が役に立ったら、いいね・ストックしてもらえると嬉しいです!