pipe.cc device.cc
ようやくマルチプロセスでマルチスレッドな泥沼になってしまったProcessクラスを再設計。
パイプからread()システムコールで読み込む前に、fcntl()システムコールでO_NONBLOCKフラグを設定しておくと、「読み込もうとしたけど、まだ書き込まれていない」ときに処理が停止せずにすぐ-1が返ってきて、errnoに定数EAGAINが設定される、らしい。manpage活躍。
ということで「複数のパイプのどれかから文字列を読み取れたら返ってくる」とか、「パイプごとにstd::ostreamを割り当てて、それぞれに順次出力させる」という処理が、スレッドなしで実装できた。
「参照の参照」で、std::ostream&をstd::pairに入れようとしてしばしハマってしまったものの、とりあえずポインタ(std::ostream*)を入れることにしてしのぐ。どうするのが良いのかな?
それで今日はDeviceクラスと、それを継承してVirtualDeviceクラスとPhysicalDeviceクラスを作成。procやらsysfsやらtmpfsやらはVirutalDeviceで、major:minorなデバイスノードを持つのがPhysicalDevice。Deviceクラスにはmount()とかumount()などなどの純粋仮想関数なインターフェースを。C++を勉強しながらプログラミング中。
これで/procと/sysをマウントできた。これでとブートパラメータ(/proc/cmdline)を入手できて、ハードウェアの自動検出ができるようになる。
次はブートディスクの検出。ひたすらマウントを試して、特定の名前のファイルがあるディスクを探す処理。
ひたすらマウントしまくるなんて時間がかかりそうと思うと、これがそうでもない。「CDは/dev/hdcでファイルシステムはiso9660だろう。/dev/hdcでなければ/dev/hda、/dev/hdb、/dev/hddとiso9660で試して、そうでなければUSB外付けと判断して/dev/sda、/dev/sdbをiso9660で。ここまで来て違うならHDDかUSBメモリ。となれば/dev/hda1…とNTFSで試して、/dev/sda1、/dev/sdb1とFAT32で試す」とか予測してマウントを試すと、すぐにヒットする。それに/proc/partitionsを見ると
3 0 8192016 hda 3 1 7727233 hda1 3 2 1 hda2 3 5 457821 hda5
などなどと書いてあって、ここから少なくともhda2は拡張のヘッダだとわかるから飛ばす。hda*がある時点で、CDではないから後回し。それに/dev/*はudevを使って作成するので、そもそもUSBデバイスなどが接続されていなければ、/dev/sd*は存在しないので、試さないといけない候補はそれほど多くない。
さらにハードウェア自動検出ツールを自作して、デバイス名までわかるので、「USB Memory」とか「Stick」とかの単語を発見したら優先して/dev/sd*を検索する、などなどの策もとれる。
その分、プログラミングが大変と…。
とりあえずは何も考えないでマウントしまくって、後で改善しよう。