User Tools

Site Tools


jp:doc:techref:process.boot

起動プロセス

requirements.boot.processも参照してください。
このガイドは最新ではありません!またprocdには触れていません。

このガイドは以下を理解する時に役立ちます。

プロセストリニティ

装置への電源投入時、極めて基本的な最下層のハードウェア要素が実行されます。JTAG Portへの接続を通して命令を発行できます。

ブートローダ(bootloader)

  1. フラッシュ上の bootloader が読み込まれます。
  2. ブートローダーは下層ハードウェアの初期化(POST)を実行します。
  3. ブートローダはフラッシュメモリにある圧縮されたカーネルイメージをメインメモリ(=RAM)へ展開します。
  4. ブートローダーはinit=… オプション(デフォルトは /etc/preinit)と共にカーネルを実行します。

カーネル(Kernel)

  1. カーネルはブートストラップ自体を進めます。 (原文!)
  2. コマンド/オペレーションコード start_kernelを発行します。
  3. カーネルは有効なスーパーブロックとして、mtdパーティションのrootfsを探し、見つけたらSquashFSパーティション (/etcを含む) をマウントします。(詳しくは、technical.details)
  4. /etc/preinitは初期化事前ステップです。(ディレクトリの作成、fsのマウント、/proc、/sys、… )
  5. カーネルはrootfs (root file system)の下に他のパーティション(例えば、jffs2 partition)をマウントします。flash.layoutpreinit and root mountを参照、また udev FIXME確認してください
  6. もし"INITRAMFS"が定義されていない場合は/sbin/init (全てのプロセスの親)が呼ばれます。
  7. 最後に、カーネルスレッドが ユーザスペースのプロセスinitになります。

Init

カーネルがrootfsをマウントするとユーザスペースが開始され、実行の初期プログラム(デフォルト)は/sbin/initです。 アプリケーションとカーネル間のインターフェースは、clibとsyscallsであることを思い出してください。

  1. initは"sysinit"の入り口として/etc/inittabを読みます。 (デフォルトは"::sysinit:/etc/init.d/rcS S boot")
  2. initは/etc/init.d/rcS S bootを呼び出します。
  3. rcSは executes the symlinks to the actual startup scripts located in /etc/rc.d/S##xxxxxxに置かれた実際のスタートアップスクリプトへのシンボリックリンクを"start"オプションと共に実行します。
  4. rcSの完了後、システムが立上げ実行されます。

オリジナルスタートアップスクリプト

注: opkgにてインストールするPackagesは おそらく追加的なスクリプトになります。

S05defconfig OpenWRTインストール後の最初に起動時にプラットフォーム用のconfigファイルをデフォルト値で作成します。(/etc/defconfig/$board/から/etc/config/へコピーします。)
S10boot hotplug-script、ファイルシステムのマウント、starts ..、starts syslogd, …開始
S39usb mount -t usbfs none /proc/bus/usb
S40network ネットワークサブシステム(run /sbin/netifd, up interfaces and wifi)の開始
S45firewall /etc/config/firewallからファイヤウォールルールの作成と実装
S50cron crondの開始。/etc/crontabs/rootをご参照ください。
S50dropbear dropbear開始。 /etc/config/dropbearをご参照ください。
S50telnet root パスワードのチェック。設定されていない場合は/usr/sbin/telnetdからスタート
S60dnsmasq dnsmasqの開始。 /etc/config/dhcpをご参照ください。
S95done /etc/rc.localの実行。
S96led /etc/config/system からLEDの設定読込とセットアップ。(/sys/class/leds/*/*へ値を書き込み)
S97watchdog watchdog daemonの開始。 (/sbin/watchdog)
S99sysctl /etc/sysctl.conf 解釈

init デーモンは常に実行され、シャットダウンコマンドにて、 initは、

  1. シャットダウンのため/etc/inittab読込。(デフォルトは"::shutdodwn:/etc/init.d/rcS K stop")
  2. /etc/init.d/rcS K stop呼び出し。
  3. rcSは、/etc/rc.d/K##xxxxxx に置かれたシャットダウンスクリプトを"stop"オプションと共に実行。
  4. システムは停止/リブート
K50dropbear dropbearの全てのインスタンスを終了
K90network 全てのインターフェースの停止とnetifdの終了
K98boot ロガーデーモンの終了: /sbin/syslogd and /sbin/klogd
K99umount キャッシュのディスクへの書き出し、ファイルシステムのアンマウント

詳細な起動シーケンス

ブートローダ(Boot loader)

ブートローダ(この事例ではgrub)の初期化およびブートメニューのオプション解析の後、カーネルをロードします。

通常ブートのopenwrt-x86-ext2-image.kernelファイル記載の事例:

  • "kernel /boot/vmlinuz root=/dev/hda2 init=/etc/preinit [rest of options]"

このboot/grub/menu.lstファイルの記載は、カーネルは/bootの下のディレクトリにあるファイル名vmlnuzであることをgrubへ伝えます。 他のラインは、カーネルに渡されるオプションです。カーネルがどのように開始されるかを知るために/proc/cmdlineファイルを読むことでオプションが調べられます。デバイスへのログインによって、どのようなオプションがgrubから引き渡されたのかを"cat /proc/cmdline"とタイプすることで確認できます。

テストシステムのロード時にカーネルへ引き渡されたオプションは以下です。:

  • "root=/dev/hda2 rootfstype=ext2 init=/etc/preinit noinitrd console=ttyS0,38400,n,8,1 reboot=bios"

オプションは:

  1. root: OpenWrtのその他のシステムが置かれたルートデバイス/パーティション。
  2. rootfstype: ルートパーティションのフォーマット - この例ではext2。
  3. init: カーネルのロード、初期化後の最初のコール
  4. noinitrd: カーネルへビルドされたシステムの他の部分にアクセスするための全てのドライバ
  5. console: フロー制御なしの38400速度、8bitデータと1ストップビット時のttyyS0(最初のシリアルポート)への通信からログインコンソールコマンドを許容するデバイス。他のオプションはカーネルドキュメント参照。
  6. reboot: 不明確であるが、リブートがどのように振る舞うかをカーネルに伝えるオプションと考える。

ブートローダのカーネルオプションのエントリへカーネル読み込後、最初のプログラムがコールされます。grubでは、エントリは/boot/grub/menu.lstファイル内にopnewrt-イメージカーネルイメージファイルとして置かれている。

[ 注: 全てのgrubパラメータ知るにはgrubのマニュアルを参照] この事例の記載、"init=/etc/preinit"は初期化後の最初のプログラムの実行は、"/dev/hda"ディスク上の"hda2"パーティションに置かれた"/etc"ディレクトリで見つけられる"preinit"であることをカーネルに伝えています。

/etc/preinit スクリプト

preinitスクリプトの主要な目的はスタートアップスクリプトの残り部分の初期チェックと設定です。/procと/sysを疑似ファイルシステムとしてマウントすることが主要な仕事の一つで、ステータス情報へのアクセスやいくつかの制御機能が利用可能になります。もう一つの主要な機能は、コンソール、tty、メディアデバイスのようなものへのアクセスするために/devディレクトリのを準備します。最後の仕事はinitデーモンプロセス自体の開始です。

Busybox init

Initは、デーモンの開始、ランレベルの変更、デーモンへアクセスするコンソール/疑似コンソール/ttyの設定やその他の管理も行うことから「全てのプロセスの親」と考えられています。

initが開始されると/etc/inittabのコンフィグレーションファイルを読み、特定の活動のためにどのプロセスを開始、監視し、関連するプログラムのコールのきっかけの活動がいつかを示します。

Busyboxによるinitプログラムは最小限のデーモンです。それはランレベルのような情報を持たず、通常のinitコンフィグファイルと比べて多少省略されています。 もしデスクトップのLinuxが実行されているならば、"man inittab"にて通常のinitプロセスとエントリについて確認できます。フィールドはコロンで区切られ、以下の様に定義されます。

  • [ID] : [Runlevel(s)] : [Action] : [Process to execute ]

busybox initは、"ID" (1番目)、 "Action" (3番目)と"Process" (4番目)のフィールドのみ必要とされます。BusyBox initは通常のinitに対し、いくつかの注意点があります。IDフィールドはTTY/コンソールの制御に使われ、ランレベルは定義されません。最小の/etc/inittabは以下です。

  1. ::sysinit:/etc/init.d/rcS S boot
  2. ::shutdown:/etc/init.d/rcS K stop
  3. tts/0::askfirst:/bin/ash –login
  4. ttyS0::askfirst:/bin/ash –login
  5. tty1::askfirst:/bin/ash –login

IDフィールドが空欄のライン1と2は、特定のターミナルやコンソールが無いことを示します。

Notice that both the "sysinit"と"shutdown"動作は同じプログラム("/etc/init.d/rcS")が呼ばれていることに注意してください。rcSスクリプトへ渡すオプションが違うだけです。これは後に明確になります。

この時点で、initはコンフィグレーションファイルを解析して、次に何をするかを探しているので、sysinitエントリに"S"と"boot"オプションで/etc/init.d/rcSが呼ばれています。

スタート時の/etc/rc.d/rcS スクリプト

この時点で基本的な設定は完了し、全てのプログラムとシステム/構成ファイルが利用できます。そして、その他のプロセスへの準備状態になります。

rcSスクリプトの機能はかなり簡略化されています。- その一つ目的が、適切なオプションによる/etc/rc.d ディレクトリ内のスクリプトの実行です。sysinitエントリをよく見ると"S"と"boot"オプションと共にrcSスクリプトが呼ばれていることが分かります。rcSは2つのオプション("S"と"boot")で呼ばれたため、rcSは$1を"S"、$2を"boot"に置き換えます。rcSに関連するラインは以下です。

   -  for i in /etc/rc.d/$1* ; do
  2.      [ -x $i ] && $i $2
  3.  done

基本的な解析:

  1. "S"で始まる/etc/rc.d ディレクトリ内の全てのエントリ(ファイル/リンク)を順次実行します。
  2. もしファイルが実行形式であれば、"boot"オプションと共にファイルが実行されます。
  3. $iを次のファイル名に置き換え、ファイルが見つからなくなるまでステップ1を繰り返します。

マイクロソフトのプログラムと違い、Linuxではファイル拡張子ではなく、ファイルパーミッションによって実行形式かどうかが示されます。ファイルパーミッションの説明については、Linux/Unixマシンの"man chmod"にてパーミッションと実行形式ファイルを参照してください。

/etc/rc.d ディレクトリを見るとスタートアップのための関連リンクや、shutdown時には無いスクリプト(すなわち/etc/init.d/httpd)や一方でスタートアップには無いshutdownのスクリプト(すなわち/etc/init.d/umount)があることに気付くかもしれません。

httpd(Webサーバ)の場合、それが死んでいるかどうかは問題ではないので、退去時にクリーンアップする必要がありません。

一方で、ストレージメディアに関連するumountスクリプトは、全てのデータがメディアへフラッシュされたことを確認しシャットダウン前に必ず、実行されなければなりません。さもなくばデータの破損が起こり得ます。どこか(/etc/preinitのような)でメディアのストレージマウントは取り扱われるので、スタートアップ時にはumountを呼ぶ必要はありませんので、スタートアップスクリプトにはこれはありません。

最後のスタートアップスクリプトが実行されると完全なOpenwrtシステムとなります。

ノート

jp/doc/techref/process.boot.txt · Last modified: 2017/04/28 05:00 by seiji.komine