Lions' 本読み (123)
v6-unix-okinawa なスライドの 92 枚目。と初期化のあたりの突き合せについて。
マンガになってるのは以下の五箇所の継続な断点 (?) です。
- Boot 直後
- 仮想記憶有効
- 最初の newproc
- 最初の exec
- init の実行
とりあえず、ここはポイント高いと見ているので纏めを作っておく方向で。
Boot 直後から仮想記憶有効、のあたり
これは start 以降、という理解で良いはず。で、sp 設定して云々なあたりは Lions' 本読み (122) にメモを残しています。次あたりで時間切れになった模様。
start では
- カーネルモードの PAR および PDR の初期化
- sp 設定されて仮想記憶有効化
- _edata から _end までの領域 (カーネルの BSS) が clr でゼロ初期化されて
- _u な領域も clr でゼロ初期化
- PS の前モードをユーザにしてそれ以外は 0 で初期化
- main 手続き呼び出し
を行ないます (ざっくりですが)。
per process data area について
テキスト 309p に領域の大きさに関する記述がありますね。
プロセス固有データ領域 (per process data area) として知られている 512 ワード長領域の先頭位置である。
Lions' Commentary on UNIX より引用
ええと、308p の 632 の解説を読んでみるに、_仮想記憶有効_の図の u の領域を云々しているのが 632 以降の処理になっている模様。あ、ここは PPDA を指す PAR と PDR を初期化しているのか。
例の参考書籍によれば、ここで初期設定される PAR は 01400 で PDR は 007406 に、という記述がありますね。ちなみに
0636 mov $USIZE-1\<8|6,(r1)+
ですが、USIZE は 16 で #define されているので 1111 を 8bit 右左に shift して 6 とビット和をアレすると例の資料にある通り、007406 になりますね。$_end の値を確認、なソレは #geektable とかで確認してみたら良いかも。
最初の newproc
で、main 手続きに突入してスデにマンガでは user 領域が二つありますね。これはそういった意味では 1635 なあたり、という事になるのか。
それまでに何がどうなって user なソレが二つになっているのか、というあたりがアレな訳だったりします。テキストの 311p の下らへんから 315p のあたりですね。
proc[0] の初期設定、のあたり
311p で proc[0] の領域の以下で初期設定している属性以外はゼロで初期化された状態とのことです。
1589 proc[0].p_addr = *ka6; 1590 proc[0].p_size = USIZE; 1591 proc[0].p_stat = SRUN; 1592 proc[0].p_flag =| SLOAD|SSYS; 1593 u.u_procp = &proc[0];
テキスト 312p に解説があります。ka6 が指す領域には PPDA があり、PPDA の中にある user 構造体の u_procp という属性に proc[0] のアドレスが格納される、ということになっていることが分かります (相互に参照)。
また、ここで 0 番目のプロセスのための PPDA が確保された、という理解で良いのかどうか。
newproc の呼び出し
312p の記述てきには newproc の中身は別途、ということになってますが、ちょっとだけ。基本的には 312p に書かれている通り、
- proc[1] の初期設定
- コアにプロセス固有データ領域の割り当て
を行ないます。この割り当てられる PPDA がマンガにあるもう一つの user になる訳です。簡単に書いてしまうと newproc 手続きの以下のあたり。
1896 a2 = malloc(coremap, n); (snip 1910 /* 1911 * コアがあるので、コピーする 1912 */ 1913 rpp->p_addr = a2;
プロセス #0 の p_addr はマンガのあの領域ですが、proc[1].p_addr はちょっと異なる領域、ということに今のところはなっています。
この状態で newproc 手続きは 0 を戻し、main 手続きは sched() 手続きを呼び出します。この項まだまだ続きます。312p にある通り、呼び出した sched() 手続きは戻りません。
一旦中断
このエントリ、在沖縄のある方に向けて書いてたりするんですが、このあたりが例の参考書籍の 8p あたりになります。sched() 手続きが呼び出されてから
- sched()
- sleep()
- swtch()
と順に手続きを呼び出していき、swtch() の中で sureg() 手続きが呼び出されて swtch() が return するあたりがここの部分のクライマックスとなっています。
詳細については別途纏める方向ですが、某所で色々とやりとりできればと思ってます。