Lions' 本読み (108)

気持ちを落ち着けて wdir を読む朝。
テキストの 404p には_ディレクトリエントリを書き込む_という記述がありますね。ぬ、ディレクトリエントリの仕様に関する記述も同じページにあります。

  • ディレクトリエントリは 512byte なブロック 1 つ以上で構成される
  • 512bytes なブロックは 16bytes 単位で 32ブロックに分割される
  • 16bit の inode テーブルへのポインタと 14 bytes の文字からなる

namei という手続きがディレクトリの検索な模様。
で、wdir なんですが、408p に解説がありますね。曰く

16 文字のディレクトリエントリを構造体 u.u_dent へコピーして、ここからディレクトリファイルに書き込む (u.u_dent の前の内容がディレクトリファイルの最後のエントリ名であったことに注意してほしい)。
この手続きは、ディレクトリファイルがすでに検索済みであり、ディレクトリファイルの i ノードがすでに割り当てられていて、u.u_offset の値が適切に設定してあることが前提になっている。

Lions' Commentary on UNIX より引用
とりあえず user 構造体のリハビリ (?) が必要。とりあえず順に見てみます。

7477 wdir(ip)
7478 int *ip;
7479 {
7480    register char *cp1, *cp2;
7481
7482    u.u_dent.u_ino = ip->i_number;
7483    cp1 = &u.u_dent.u_name[0];

引数の ip は inode 配列な struct inode になるのか。というかこの手続き、ざっくりな構造として

  • ユーザ構造体の属性を云々して
  • u.u_pdir を writei して
  • u.u_pdir を iput

という形になってますね。
で、上で引用した部分の下二行ですが_カレントディレクトリエントリ_な属性ですね。

0431 struct  {               /* カレントディレクトリエントリ */
0432    int  u_ino;
0433    char u_name[DIRSIZ];
0434 } u_dent;

で、cp1 に u_dent.u_name の先頭アドレスを設定した後で以下。

7484    for(cp2 = &u.u_dbuf[0]; cp2 < &u.u_dbuf[DIRSIZ];)
7485            *cp1++ = *cp2++;

u.u_dbuf の中身を u_dent.u_name にざくっとコピィしているのか。ちなみに u_dbuf は_現在のパス名の要素_とコメントされてますね。
で、もう少し属性設定。

7486    u.u_count = DIRSIZ + 2;
7487    u.u_segflg = 1;
7488    u.u_base = &u.u_dent;

それぞれの属性のコメントですが以下。

  • u.u_count は _IO に対する残りバイト数_
  • u.u_segflg は _IO 用フラグ、ユーザー空間かカーネル空間か_
  • u.u_base は _IO 用ベースアドレス_
  • ちなみに u_udent は先に引用した通り _カレントディレクトリエントリ_

むむ、よう分からんな。writei 手続きと iput 手続きを確認した方が良いのかどうか。それぞれの呼び出しは以下の形になってます。

7489    writei(u.u_pdir);
7490    iput(u.u_pdir);

u_pdir 属性は親ディレクトリの i ノード、とのことなので、これは正にディレクトリエントリに何かを書き込んでいる、ということになるのかどうか。

writei (6276)

手続き定義のコメントを以下に引用。

6267  * 引数が指す inode に
6268  * 対応するファイルを書き込む
6269  * 実際の書き込み引数は次の
6270  * 変数に存在する。
6271  * u_base          転送元のコアアドレス
6272  * u_offset        ファイル中のバイトオフセット
6273  * u_count         書き込むべきバイト数
6274  * u_segflg        カーネル / ユーザーへの書き込み

ええと、inode 番号とファイル名が書き込まれた u.u_dent 属性を書き込んでますね。ちっと時間が無いので中身掘削は別途で。

iput (7344)

ここも手続き定義のコメントを引用すると

7388  * inode 構造体の参照カウントを
7389  * デクリメントする。
7390  * 最後の参照のとき、
7391  * inode を書き出し、必要ならば
7392  * ファイルのディスクブロックを解放する。

なんで親ディレクトリの参照カウントをデクリメントしなきゃ、なのかが謎。writei 関連で i_count が ++ されるのかな。
ここは宿題。時間切れ。