UNIX 6th code reading - 基本入出力入門
はじめに
今回は15章を見ていきます。周辺デバイスとの入出力に関する章です。
参考資料
- The Unix I/O System
- Lions本で参考文献として挙げられている論文
-
- 2238クラブに置いてありました。感謝 http://www.tom-yam.or.jp/2238/ref/index.html
- UNIXカーネルの設計
- 3章のバッファキャッシュが参考になりました。17章を読むときも参考になりそうです
- http://www.amazon.co.jp/dp/4320025512
デバイスの種類
デバイスには2種類あります。
バッファ(ブロックデバイスへのアクセス方法について)
バッファとは
ブロックデバイスにはバッファを使ってアクセスします。バッファはソフトウェア上での仕組みです。ハードとしてバッファというものがあるわけではありません(たぶん)。デバイスドライバについては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のパラメータをセット
- 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章までは順調に書けそうな予感です。