ルートファイルシステムが読み込まれる前に、デバイスに対する処理を挟む (その1)
今回から数回に分けて GNU/Linux (以下、Linux) において、ブート時にルートファイルシステムが読み込まれる前に、特定のデバイスに対して処理を行う方法について考察し、最終的に実際にプログラムを記述してみる。
かなり内輪なネタだが。以下で述べる処理は、特定デバイス (以下、キャッシュデバイス) によって永続キャッシュされたデータを、ブート時のカーネルをロードしルートファイルシステムを初期化する直前に、キャッシュデバイスで指定されたデバイスに対して書き戻す際に役に立つ。
行いたい処理は以下の 3 つ。
(1) ブートローダからの値の受け渡し
(2) ブートシーケンス中に処理を挿入
(3) 挿入する処理 : キャッシュデバイスに蓄えられた永続データの書き戻し処理
今回は (1) と (2) について解説し、(3) について考察する。
まずは "(1) ブートローダからの値の受け渡し" について。
リアルモードのブート中に取得したデータ (ブートパラーメタ) をプロテクトモードで動作するカーネルで扱う為の常套手段として、カーネルがロードされるメモリ領域とは別の領域にデータを書き込み、メモリ管理機構の初期化を行う前に、データの回収を行うというやり方がある。
Linux では、ブートローダから渡されたブートカーネルパラーメタを boot_command_line に格納する。そして、setup_command_line() [init/main.c] でカーネルのデータ領域へコピーする。
以降、データ領域に移された saved_command_line を参照する事で、任意をブートパラメータをカーネル側で処理する事ができる。
次に "(2) ブートシーケンス中に処理を挿入" について。これは、どこで処理を挿入すればよいか、という話である。
ページテーブルやら、割り込みテーブルやらのハードウェアの初期化処理が修了すると、カーネルは start_kernel() [init/main.c] 関数を呼び出す。ここでは、メモリ管理システムやらの初期化を行い、カーネルスレッドを生成し、そこで init プロセスが生成される。これ以降では、システムが停止するまで、無限ループに落ちる。
ルートファイルシステムの初期化処理は start_kernel() から呼び出される prepare_namespace() [init/do_mounts.c] から行われる。
prepare_namespace() の内部では、ブートローダの root パラメータで渡されたデバイス名から dev_t 型オブジェクトで表されるデバイス番号 (デバイスのメジャー番号とマイナー番号をくっつけた 32 bit のデータ構造) を取得し initrd_load() [init/do_mounts_initrd.c] を呼び出す。prepare_namespace() はこれに成功すると sys_mount() を呼び出し、ルートファイルシステムをマウントする。
最後に "(3) キャッシュデバイスに蓄えられた永続データの書き戻し処理" について考察する。
(2) で示した initrd_load() より前に、キャッシュデータの書き戻し処理を行えば、カーネルがファイルシステム参照前に、キャッシュデータをディスクに書き戻す事ができそうである。
しかし、書き戻し処理はそう簡単には行えない。この時点では、デバイスサブシステムの初期化処理を行っていないので、全てのブロックデバイスを統合するリスト (all_bdevs) からキャッシュデバイスはおろか、全てのデバイスに対するブロックデバイスオブジェクトを参照できない。
I/O をキューに格納し、処理をさせる為には、これの生成処理を自前で容易しなければならない。
ブートシーケンスにおいて、この処理を行う手段について、次回以降で示す事にする。
- Category(s)
- 学習経過
- The URL to Trackback this entry is:
- http://dev.ariel-networks.com/Members/ohyama/30eb30fc30c830d530a130a430eb30b730b930c630e08aad307f8fbc307e308c308b524d306b300130a430b9306b5bfe3059308b51e674063092631f3080-305d306e1/tbping