Linuxのブートシーケンスの基礎まとめ
ファームウェア(BIOS or UEFI*1)が
- マザーボードのROMからメモリにロードされて実行開始し、ハードウェアをスキャン(POST - Power-On Self Test というハードウェアの自己診断を)する
- [BIOSの場合] プライマリHDDのMBR(先頭のセクタ(512バイト))を見る
- [UEFIの場合] プライマリHDDのGPTヘッダ(LBA1 or 最終セクタ)を見る
GPTとMBRはどのように違うのか? - かーねる・う゛いえむにっき
BIOS/UEFI/MBR/GPT
- MBRでは232≒2.2TBまでのディスクしか扱えない
GPTでは264≒8.5ZBまでのディスクを扱うことができる
BIOSはIntel CPUのリアルモード(16bitモード)でないと起動できないため、1MBまでのメモリしか利用できない
- UEFIはプロセッサ非依存のため、32bitプロセッサなら32bit命令が、64bitプロセッサなら64bit命令が使えるため、潤沢なメモリを利用できる
MBRのパーティションテーブルには四つのパーティション構成情報が書き込める (四つ以上は、四つ目を拡張パーティションテーブルとして対応)
- MBRの最後の2バイトは
0xaa55
というMBR signatureが書き込まれている
$ sudo hexdump -s 500 -n 12 /dev/sda 00001f4 0000 0000 0000 0000 0000 aa55 0000200
一方、GPTは128までパーティションが管理でき、物理や論理といった煩雑な管理は必要ない
末尾にもGPTヘッダがあり冗長構成となっている
2TB以上のディスクは
- MBRでは扱うことができない and
fdisk
コマンドでは扱うことができない GPTを使う必要がある and (
parted
orgdisk
コマンドを使う必要がある )追加した2TB以上のディスクにパーティションラベルを付ける
# parted /dev/sdd (parted) mklabel gpt
ブートローダ(GRUB or LILO)が
GRUB2
- MBRに含まれるGRUB Stage 1をロードする
- GRUB Stage 1が、MBRと最初のパーティションの間に置かれているGRUB Stage 1.5をロードする
- Stage 1.5が、bootパーティションのファイルシステムをマウントするためのドライバを持っており、/boot/grub/からStage 2をロードする
- Stage 2が、カーネル選択メニューを表示する
initrd/initramfs
- initrdはブロックデバイスをgzip圧縮したもの
- initramfsはファイルシステムをcpioでアーカイブしたものをgzip圧縮したもの
- initrdにカーネルモジュールを追加しようとするとマウントが必要(etc.)
→ 扱いにくいのでObsolete
→ 現在では一般的にinitramfsを使う - initrdに含まれるファイルにアクセスするためにループバックマウントされる
initrd/initramfsの必要性
- カーネル本体に(ドライバ等の)モジュールを直接組み込んでおくよりも、カーネル外部に(ファイルとして)存在するカーネルモジュールを必要なときに必要なだけ組み込む方が、カーネル本体を軽量にかつ汎用的に扱うことができる
- ルートファイルシステムをマウントするために必要なファイルシステムのドライバを、別のルートファイルシステムにモジュールとして保存しておいて、マウントする前にカーネルにロードする
- この「別のルートファイルシステム」を担うのがinitrd/initramfsであり、これは「初期ルートファイルシステム」、あるいは、ramfsとしてメモリ(RAM)上にマウントされるため「初期RAMディスク」、と呼ばれる
vmlinuz/vmlinux/bzImage/zImage
- bootパーティションには、vmlinuzと呼ばれる、カーネルイメージを含むファイルが置かれている
- vmlinuzは、カーネルイメージ(vmlinux)をgzip圧縮したものと、圧縮されたカーネルイメージを伸張し展開するコードをそれ自身に伴った形式ものである
- このファイル形式をbzImageという
- なお、zImageでは512KB以下のイメージしか扱えない
uImage
- U-Boot用のカーネルイメージのファイル形式
- U-Bootは、主に組み込み用途で使われるブートローダで、ネットワークブート(PXEクライアント)の機能を持つなど、高機能版のブートローダ(GRUBでネットワークブートをする場合は、おそらくNIC側のPXEクライアント機能を使う必要がある)
System.map
- System.mapは、vmlinuxに対するnmコマンドの実行結果であり、カーネルに関するメモリアドレスと型、シンボルの対応テーブルを表す
- nmは、実行形式のファイルやライブラリなどからシンボルテーブルを取得するためのコマンド
- ブートに必要なデータではなく、Kernel PanicやOopsが発生した際のデバッグに使われる(実行時のメモリアドレスからシンボルを特定する)
kexec
カーネルが
- ハードウェアリソースに対応する初期設定やデバイスドライバの初期設定を行う
- idleプロセス(PID=0)を起動する
- initrd/initramfsを展開して、初期ルートファイルシステムをramfsとしてマウントする
- [initrdの場合] /linuxrcを、一時的なinitプロセス(PID=1)として起動する
- [initramfsの場合] /initを、一時的なinitプロセス(PID=1)として起動する
- 初期ルートファイルシステムに置かれているカーネルモジュールをロードして、様々なファイルシステムでフォーマットされているパーティションを認識する
- 初期ルートファイルシステムから、読み込み専用でマウントしたルートファイルシステムへマウントポイントを移す
- [initrdの場合] 一時的なinitプロセスの終了後に、/sbin/initを実行して、initプロセス(PID=0)を起動する
- [initramfsの場合] /initが、exec /sbin/initを実行して、initプロセス(PID=0)を起動する(execは現在のプロセスを別のプロセスで置き換える)
Systemd
- /sbin/initは、現在systemdに置き換えが進んでおり、単に/sbin/initがsystemdへのシンボリックリンクになっているLinuxディストリビューションも存在する
- systemdは、サービスの起動を並列に実行することによる起動処理の高速化、cronやxinetd(リソース効率化のため通信を検出した際にそのポートに対応するプロセスを起動するスーパーデーモン)に対応する機能の集約、cgroupによるリソース制御を用いたプロセスの優先度管理、などを行う
initプロセスが
- /etc/inittabに書かれている通りrunlevelを設定し、該当する/etc/rc.d/rcXを実行する
- スクリプトを実行する際は、forkによってinitプロセスがそのスクリプトを実行するプロセスの親プロセスとなる
- 読み込み専用でマウントされたルートファイルシステムに対して
fsck
を実行*2し、実行後に読み書き可能で再マウントする - initプロセスが、/etc/fstabに書かれている通り各パーティションをマウントする
runlevel
- runlevelの定義はOSに依存するが、0:停止、1:シングルユーザ、2:マルチユーザ(ネットワーク無、Xディスプレイ無)、3:マルチユーザ(ネットワーク有、Xディスプレイ無)、5:マルチユーザ(ネットワーク有、Xディスプレイ有)、6:リブート、のパターンが多い
- Sで始まるファイルは起動用スクリプト(S=Start)であり、Kで始まるファイルは停止用スクリプト(K=Kill)になる
…