【Linux】ブートローダーからカーネルまでの起動プロセス

Linux起動プロセス Linux
スポンサーリンク

Linuxの起動手順に関してまとめました。

起動手順はアーキテクチャによって異なるため、x86系についてまとめました。

Linuxの起動順

Linuxの起動手順は次の手順で起動します。

①電源投入
②BIOS:先頭セクタのMBRを読み込む
③ブートローダ:マスターブートレコード(MBR)・ブートローダの起動
④カーネル:システムの設定と初期化
⑤initプロセス:最初に起動するプロセス(PID:1)
 /etc/inittabに基づいて/etc/rcスクリプトを実行する。

BIOSとUEFI

ここでは、旧来のBIOSとUEFIの2つについて調べてみました。

BIOS(Basic Input / Output System)

Linuxだけでなく、ほとんどのPCにおいて、ローレベルな制御プログラムとして組み込まれているのがBIOSになります。

BIOS(Basic Input/Output System)は不揮発性メモリに格納されており、基本的な入出力の管理を行います。

BIOSは電源投入後に、最初に実行される命令であるリセットベクターが、メモリ内のプログラムを実行することで、

デバイスの初期化を行い、決まった手順に従ってブートローダーにCPUの制御を移行します。

ここの手順は非常に複雑で説明が難しいですが、主な実行される作業内容は以下の通りです。

・メモリのチェック
・ハードウェアの設定の読み込み(自己診断と初期化)
・起動デバイスのチェック
・起動デバイスのブートローダーの実行

これまでBIOSは、マザーボード上にフラッシュメモリーBIOSが主流でしたが、現在はSPI仕様が主流になっているそうです。

旧来のBIOS

旧来のBIOSには次のような不便が多発しました。

・16Bit

旧来のBIOSは、最初に読み込まれるコードが16bitであったため、その後に登場した32bitや64bitのOSに移り変わるにつれて非常に不便な存在になってしまいます。

x86系マシンは、16bitモードのメモリー空間はわずか1MBしか割り当てられえていませんでした。

PCがどれだけ容量の大きいメモリを確保していても、16bitモードからアクセス可能なメモリはわずか1MBと決まってしまいました。

1MBではカーネルを読み込むことどころか、起動するのがやっとな状態です。

・ハードディスクの制限(物理的仕様の制限)

旧来のBIOSによるデバイス管理は、CHS方式を採用していました。

CHS方式は、ハードディスクの記録単位である、シリンダ、ヘッド、セクターを検索し読み込む方式です。(詳しい説明は色んなサイトに掲載されているので割愛)

このシリンダー、ヘッド、セクタを基に、毎回探索しては入出力してを繰り返していました。

aCHS方式

ただし、これは旧来のBIOSだからCHS方式を採用していたと言わけではないです。現在は使用が変わっており、LBA方式を採用することが一般的です。

LBA方式は、先頭のセクターから最終セクターまで連番を与え、その番号でディスクの位置を管理しています。

これまでのシリンダ、ヘッド、セクタといったハード依存することなく、ディスク位置や管理をすることが可能となりました。

LBA方式

・容量制限

一部OSにおける起動ドライブの容量制限が2TBと決められている。

UEFI(Unified Extensible Firmware)

旧来のBIOSは現在となっては、かなりレガシーな存在となってしまいました。

BIOSの後継となるファームウェア規格、UEFI(Unified Extensible Firmware)が登場しました。

現在は、UEFIもBIOSといったファームの総称してBIOSと呼ばれることが多いです。

このUEFIは、これまでのBIOSの欠点を解消したものになっています。

BIOSと異なる点

・GUIベースでのセットアップ
・起動ドライブの容量制限解除
・リセットベクターに制御が移った直後、32Bit/64bitのCPUモードに切り替える
・UEFI独自のブートマネージャが存在し、そこからカーネルやブートローダを読み込んでOSを起動

ブート手順

マスターブートレコード

マスターブートレコード(MBR)は、起動デバイスの先頭セクタに格納されている情報です。

この部分では、OSを起動するためのブートローダの一部と、基本パーティションの情報を収めたパーティションテーブルが含まれています。

MBR

ブートローダ

ブートローダは、2段階に分かれています。

1.マスターブートレコードに格納されている情報(2の情報をロード)
2.マスターブートレコード情報から呼び出される情報(カーネルをロードし、カーネルに制御を渡す)

そもそも、マスターブートレコードとブートローダの2段構えの構造をしている理由は、

マスターブートレコードに格納されているブートローダのサイズが制限されており、ブートローダ全体を格納できないためです。

bootloader

カーネルの起動

カーネルは、initプロセス(/sbin/init)を最初に必ず実行します。実行内容は以下の通りです。

・ハードウェアの検出
・メモリの初期化
・システムクロックの設定
・IRQの設定
・パーティションのマウント

カーネルが起動時にどのような処理を実行したかを確認するにはdmesgコマンドを使用します。

dmesg

initプロセスと/etc/inittab

カーネルが最初に起動するプロセスがinitプロセスになります。

このプロセスは、設定ファイル/etc/inittabに基づき、様々な起動処理が実行されます。

ですが、最近/etc/inittabは見当たらないディストリビューションが出てきていると思います。

/etc/inittabの代わりに、ディレクトリ/etc/init/以下に存在する設定ファイルに各々の設定を記述する仕様になっているため、/etc/inittabは存在しません。

/etc/inittab

mxlinux@mxlinux:~
$ cat /etc/inittab 
# /etc/inittab: init(8) configuration.
# $Id: inittab,v 1.91 2002/01/25 13:35:21 miquels Exp $

# The default runlevel.
id:5:initdefault:

# Boot-time system configuration/initialization script.
# This is run first except when booting in emergency (-b) mode.
si::sysinit:/etc/init.d/rcS

# What to do in single-user mode.
~~:S:wait:/sbin/sulogin

# /etc/init.d executes the S and K scripts upon change
# of runlevel.
#
# Runlevel 0 is halt.
# Runlevel 1 is single-user.
# Runlevels 2-5 are multi-user.
# Runlevel 6 is reboot.

l0:0:wait:/etc/init.d/rc 0
l1:1:wait:/etc/init.d/rc 1
l2:2:wait:/etc/init.d/rc 2
l3:3:wait:/etc/init.d/rc 3
l4:4:wait:/etc/init.d/rc 4
l5:5:wait:/etc/init.d/rc 5
l6:6:wait:/etc/init.d/rc 6
# Normally not reached, but fallthrough in case of emergency.
z6:6:respawn:/sbin/sulogin

# What to do when CTRL-ALT-DEL is pressed.
ca:12345:ctrlaltdel:/sbin/shutdown -t1 -a -r now

# Action on special keypress (ALT-UpArrow).
#kb::kbrequest:/bin/echo "Keyboard Request--edit /etc/inittab to let this work."

# What to do when the power fails/returns.
pf::powerwait:/etc/init.d/powerfail start
pn::powerfailnow:/etc/init.d/powerfail now
po::powerokwait:/etc/init.d/powerfail stop

# /sbin/getty invocations for the runlevels.
#
# The "id" field MUST be the same as the last
# characters of the device (after "tty").
#
# Format:
#  <id>:<runlevels>:<action>:<process>
#
# Note that on most Debian systems tty7 is used by the X Window System,
# so if you want to add more getty's go ahead but skip tty7 if you run X.
#
1:2345:respawn:/sbin/getty --noclear 38400 tty1
2:2345:respawn:/sbin/getty 38400 tty2
3:2345:respawn:/sbin/getty 38400 tty3
4:2345:respawn:/sbin/getty 38400 tty4
5:2345:respawn:/sbin/getty 38400 tty5
6:2345:respawn:/sbin/getty 38400 tty6

# Example how to put a getty on a serial line (for a terminal)
#
#T0:23:respawn:/sbin/getty -L ttyS0 9600 vt100
#T1:23:respawn:/sbin/getty -L ttyS1 9600 vt100

# Example how to put a getty on a modem line.
#
#T3:23:respawn:/sbin/mgetty -x0 -s 57600 ttyS3

#-- isdnutils begin
# Change the line below for your local requirements and uncomment them.
# Use "init q" to reread inittab.
# look at the mgetty manpage for more information (mgetty isn't standard!)
#
#I0:2345:respawn:/sbin/mgetty -D -m '"" ATZ OK AT&Eyourmsnhere OK AT&B512 OK' -s 38400 ttyI0
#-- isdnutils end

/etc/inittabの書式は以下の通りです。

format_inittab

①ID:エントリを認識するためのID

②ランレベル:エントリが行う処理のランレベル

③アクション指定子:どんな処理をどのようなタイミングで実行するかを決定する

④処理内容:initが実行するプロセス内容

そして、以下の表はアクション指定子一覧です。

アクション指定子説明
bootシステム起動時に実行され。プロセスの終了を待たずに次の処理を行う。
bootwaitシステム起動時に実行され、プロセスが終了するまでの処理を行わない。
ctlaltdelCtrlキー+Altキー+Deleatキー同時押しで、SIGNALがinitに送られた場合に実行する
initdefaultデォルトのランレベルを指定する
once指定したランレベルになった時に一度だけ実行される。プロセスの終了は待たずに次の処理を行う。
respawn指定したプロセスが終了すれば再起動される。
sysintシステム起動時に、bootやbootwaitよりも先に実行される。
wait指定したランレベルになった時に、一度だけ実行され、プロセスが終了するまで次の処理を行わない。

・/etc/init/以下の設定ファイル

mint@mint-VirtualBox:~$ ls -l /etc/init
合計 8
-rw-r--r-- 1 root root  278  5月 30  2017 anacron.conf
-rw-r--r-- 1 root root 1444  3月 22  2018 lightdm.conf

起動スクリプト

プロセスやサービスの起動は、ランレベルによってルールづけられています。

どのサービスがどのランレベルで起動するかは、/etc/rc0~6.dディレクトリで確認することができます。

※0~6はランレベル

mxlinux@mxlinux:~
$ ls -ld /etc/rc*
-rwxr-xr-x 1 root root  360  4月 28 00:01 /etc/rc.local
drwxr-xr-x 2 root root 4096  4月 26 02:18 /etc/rc0.d
drwxr-xr-x 2 root root 4096  4月 26 02:18 /etc/rc1.d
drwxr-xr-x 2 root root 4096  4月 26 02:18 /etc/rc2.d
drwxr-xr-x 2 root root 4096  4月 26 02:18 /etc/rc3.d
drwxr-xr-x 2 root root 4096  4月 26 02:18 /etc/rc4.d
drwxr-xr-x 2 root root 4096  4月 26 02:18 /etc/rc5.d
drwxr-xr-x 2 root root 4096  4月 26 02:18 /etc/rc6.d
drwxr-xr-x 2 root root 4096  4月 25 11:25 /etc/rcS.d

 

例として、ランレベル5のディレクトリを確認します。

mxlinux@mxlinux:~
$ ls -l /etc/rc5.d/
合計 4
-rw-r--r-- 1 root root 677  2月 15  2019 README
lrwxrwxrwx 1 root root  26  2月 10 04:02 S01console-setup.sh -> ../init.d/console-setup.sh
lrwxrwxrwx 1 root root  22  2月 10 03:56 S02acpi-fakekey -> ../init.d/acpi-fakekey
lrwxrwxrwx 1 root root  19  2月 10 04:02 S02cgmanager -> ../init.d/cgmanager
lrwxrwxrwx 1 root root  23  2月 10 04:14 S02lvm2-lvmpolld -> ../init.d/lvm2-lvmpolld
lrwxrwxrwx 1 root root  27  4月 25 11:25 S02nfs-kernel-server -> ../init.d/nfs-kernel-server
lrwxrwxrwx 1 root root  14  2月 10 04:11 S02nmbd -> ../init.d/nmbd
lrwxrwxrwx 1 root root  17  2月 10 03:54 S02rsyslog -> ../init.d/rsyslog
lrwxrwxrwx 1 root root  21  2月 10 04:11 S02samba-ad-dc -> ../init.d/samba-ad-dc
lrwxrwxrwx 1 root root  23  2月 10 03:54 S02stop-bootlogd -> ../init.d/stop-bootlogd
lrwxrwxrwx 1 root root  14  2月 10 03:54 S02sudo -> ../init.d/sudo
lrwxrwxrwx 1 root root  13  2月 10 04:05 S02tlp -> ../init.d/tlp
lrwxrwxrwx 1 root root  29  2月 10 04:08 S02unattended-upgrades -> ../init.d/unattended-upgrades

以下のルールでファイル名がつけられています。

①このランレベルで起動するものは、ファイル名の前に「S」がつく
②「S」に続く数値は起動順を表し、数値が低いほど先に起動
③このランレベルで処理が終了するものは、ファイル名の前に「K」がつく
④サービスやプロセスの登録は、シンボリックリンクを発行する

起動したいサービスやプロセスは、/etc/rc0~6以下のディレクトリに新規にファイルを作成し、そのファイルを対象のサービスにシンボリックリンクを発行します。

サービスの起動や終了の制御は以下のようにコマンドを実行すると、制御可能になります。

sambaプロセスを制御

mxlinux@mxlinux:~
$ /etc/init.d/samba-ad-dc stop
[ ok ] Stopping Samba AD DC daemon: samba.
mxlinux@mxlinux:~
$ /etc/init.d/samba-ad-dc start
mxlinux@mxlinux:~
$ /etc/init.d/samba-ad-dc restart
[ ok ] Stopping Samba AD DC daemon: samba.
mxlinux@mxlinux:~
$ /etc/init.d/samba-ad-dc status
[FAIL] samba is not running ... failed!

主なサービス制御コマンド

コマンド説明
startサービスを開始
stopサービスを終了
restartサービスを再起動
condrestartサービスが起動している場合のみ再起動
statusサービスの状態を表示

 

サービス起動に関する補足

RHEL(Red Hat Enterprise Linux)、Ubuntuでは、servieコマンドを使用した方が主流だと思います。

その理由は、/etc/rcスクリプトで制御する方式に変わり、新たなサービス制御であるUpstartやsystemdが台頭してきているためです。

serviceコマンドと/etc/rcスクリプトは処理内容は変わりませんが、serviceコマンドの方がサービスを統一的に扱えるのも利点になるで、

serviceコマンドで制御する方法使った方が、これからは良さそうです。

参考にした資料・テキスト

 

 

 

コメント

タイトルとURLをコピーしました