UNIX 6th code reading - 基本入出力入門

はじめに

今回は15章を見ていきます。周辺デバイスとの入出力に関する章です。

参考資料

  • The Unix I/O System
    • Lions本で参考文献として挙げられている論文

バイスの種類

バイスには2種類あります。

  • ブロックデバイス
    • まとまった大きさ(=ブロック。n bytes)単位でランダム入出力が行えるデバイス。ディスクなど
  • キャラクタデバイス
    • 1文字単位(1 byte)でシーケンシャルに入出力を行うデバイス。キーボードなど


今回はブロックデバイスを扱います。キャラクタデバイスは22章で扱われるようです。

バッファ(ブロックデバイスへのアクセス方法について)

バッファとは

ブロックデバイスにはバッファを使ってアクセスします。バッファはソフトウェア上での仕組みです。ハードとしてバッファというものがあるわけではありません(たぶん)。デバイスドライバについては16章で扱います。

この方式には以下の利点があると思います。

  • プロセスはデバイスの詳細を知らなくていい
  • 「バッファを使ってデータをやりとりする」という規約さえ守っていれば、どのデバイスドライバ&デバイスでも機能する
  • バッファをキャッシュとして扱うことで、デバイスへのアクセスが減ってパフォーマンスが向上する
バッファヘッダ

データを保存するデータ部(バッファ領域)と設定やリンク情報が入っているバッファヘッダが合わさってバッファを構成しています。

バッファヘッダは4520行目でbuf構造体として宣言されています。

Lions本で「名前の付け方を誤ったものと思われる」と書かれているのは「bufという名前ではバッファ領域と混同してしますので、例えばbuf_headという名前にでもすべきだった」と言っているのだと思います。

buf.addrにバッファとして使用するコア領域のアドレスが入ります。

swap( )

バイス入出力を理解するために、実際にスワッピング処理を行うswap( )関数(5196)を追います。スワッピング処理はコアメモリと(スワップ)ディスクとのやり取りなので、コードを追うことはデバイス入出力の理解の助けとなります。

swbuf

スワッピング処理で使われるバッファヘッダはswbuf(4721)です。swap( )の中でswbuf.b_addrをその都度設定しています。つまりスワッピング処理におけるバッファデータ領域はそのプロセスのアドレスと言えます。

イメージはこんな感じです。


swap ソースコードメモ
  • 5201 : 割り込み抑制のためプロセッサ優先度を6に
  • 5202-5205 : swbufを他のプロセスが使用していたら(他のプロセスがスワップ処理の最中だったら)swbuf.b_flagsのB_WANTEDフラグを立てて寝る。B_WANTEDはswbufを待っているプロセスがあるというフラグ
  • 5206 : swbufが使用可能になったらswbuf.b_flagsのB_BUSY(swbuf使用中), B_PHYS(大量直接転送を意味する物理入出力?), rdflg(swap( )への引数。読み書きのどちらかを示す)フラグを立てる
  • 5207-5211 : デバイスの入出力を始めるためにswbufのパラメータをセット
    • 5207 : 読み書きするデバイススワップディスク(swapdev(=00000000, 4696行目参考)
    • 5208 : 読み書きするサイズ。なぜ32倍?なぜ負の値?
    • 5210-5211 : コアメモリのアドレス(16bit)を物理アドレス(18bit)に変換。コアメモリのアドレス下位10bitを6bit左シフトしてswbuf.b_addrに入れ、上位6bitを10bit右シフトしてswbuf.b_xmemに入れる。なぜこの変換でOK?b_addrとb_xmemについて要調査
  • 5212 : swapdevは0なのでbdevsw[](4656)の中からrkstrategyが呼ばれる。引数としてswbufを渡す
  • 5213 : プロセス優先度を6に上げる。5204で寝た場合、起きたときにプロセス優先度が変わっている可能性があるため再設定している?
  • 5214-5215 : rkstrategyの動作が終わるまで寝る。寝るときのwchanはPSWPと別にした方がいいはず。5204と同じwchaanで寝てしまっているので5217のwakeupで起きてしまう
  • 5216-5217 : rkstrategyの動作が終わったらswbufを待っているプロセスを起こす
  • 5218 : プロセス優先度を0に戻す
  • 5219 : swbufのB_BUSYフラグとB_WANTEDフラグをオフにする
  • 5220 : swap処理の成否をreturnする。デバイスのアクセスに失敗した場合、デバイスドライバ(rkstarategyなど)によってswbuf.B_ERRORがセットされる


swapの流れを絵にしてみました。

終わりに

swapのコードを追っただけですが入出力の基本的な部分が理解できたと思っています。bdevswやdevtabについてはあまり触れませんでした。後の章で必要になったときに扱おうと思います。

Lions本でも振れていますが、もう少しsplnの使い方を詳細に追いたいです。リエントラント性についても。

次回は16章について書く予定です。今回のエントリを書くために入出力周りやバッファ周りを色々調べたので17章までは順調に書けそうな予感です。