Lions' 本読み (50)

朝練メモ。exec とか fork とかなあたり。あちこち自分勝手に jmp しまくってましたが、ここらへんで先頭から再読かな、と思ってます。

exec 手続き

最も長い、とある通り、200 行近い規模。ブロック的にざっくり以下なカンジらしい。

  • ファイル名から i-node オブジェクトを取得して権限などのチェック
  • ディスクバッファ (?) を割り当てて引数を詰めこむ
  • セグメントサイズ取得のため、ファイルの先頭 8 byte 読込み
  • 取得したセグメントサイズを元にユーザーセグメンテーションレジスタの初期化
  • コアの割り当て、初期化
  • データセグメントのロード
  • スタックセグメントの初期化
  • 後始末をしてリターン

最後らへん、微妙な流し方かも。で、以下な核心部分ですが

3128    xfree();
3129    expand(USIZE);
3130    xalloc(p);
3131    c = USIZE+ds+SSIZE;
3132    expand(c);
  • xfree 手続きで現状アタッチしてるテキストセグメントな参照を解放
  • プロセス固有データな領域サイズに変更
  • xalloc 手続きでいったんスワップアウトするはず
    • スワップインした時点で 3131 から実行を再開、という理解
  • 初期スタックサイズ+データセグメントのサイズ+プロセス固有データ領域なサイズに変更

ちなみに xalloc でテキストセグメントが exec するプログラムに書き変わる (という言い方も微妙ですが) 形になっているはず。
あと、微妙に気になっているのが以下。

3138    estabur(0, ds, 0, 0);
3139    u.u_base = 0;
3140    u.u_offset[1] = 020+u.u_arg[1];
3141    u.u_count = u.u_arg[2];
3142    readi(ip);

0 番地に読み込んでいるんですが、これに似たナニを xalloc で発見 (というかどっかで見た記憶が残っていた)。

4459    estabur(0, ts, 0, 0);
4460    u.u_count = u.u_arg[1];
4461    u.u_offset[1] = 020;
4462    u.u_base = 0;
4463    readi(ip);

上記、テキストセグメントを読込む処理の記述ですね。374p の記述によれば_情報は、ユーザーアドレス空間のゼロ位置から始まる領域に読み込まれることになる。_(Lions' Commentary on UNIX より引用)とあります。
ええと、基本的にユーザーアドレス空間てのはデータセグメントの先頭って理解で良いのかな。020 スキップしてるのはプロセス固有データ領域のはず。estabur の呼び出しは念の為、という理解なんですが再読するなかでもっと深く理解できますように。

fork 手続き

面白い。以下なカンジで子プロセスになるであろう proc な要素を選んでるんですが、

3327    for(p2 = &proc[0]; p2 < &proc[NPROC]; p2++)
3328            if(p2->p_stat == NULL)
3329                    goto found;

この後呼び出される newproc でも同じ要素が選択されるの前提になっている模様。曰く_newproc も同じように独自に proc を検索する。おそらくそれは、検索した値を報告しないので、常に fork と同じ空きスロットを指し示す (なぜこの点に関して混乱がないのだろうか)。_(Lions' Commentary on UNIX より引用) とのこと。
で、newproc は proc 配列に呼び出し元のコピーな形で要素を一つ確保するんですが

  • 親プロセスには子プロセスの pid
  • 子プロセスには親プロセスの pid

が戻る模様。
ちなみに混乱がない理由としては_ゆっくりだから_という理解で良いのだろうか。