MochiOS@仮想ファイルシステムの作成part10

MochiOS@仮想ファイルシステムの作成part10

前提知識無しで作るなんちゃって仮想ファイルシステムpart10。

開発日記です。独り言です。

これまでのあらすじ

part 内容
0 仮想ファイルシステムを作りたい宣言をする。
1 ざっくり仮想ファイルシステムの機能を決める。
が、機能呼出し先の仮想ファイルシステムのタスクIDをどう取得するかという問題に気付く。
2 カーネルにタスク名登録機能を実装した。
これでタスク名からタスクIDを取得する事が出来る様になるハズ、なので試したいが試す方法が無い事に気付き、ログ出力タスクの開発を宣言する。
3 ログ出力の為に使うvsnprintf()の仕様を調べる。
4 ログ出力タスクを開発してタスク名からタスクIDの取得機能が正しく動いている事が確認できた。
5 mount機能を実装した。たぶんできてる。
6 FDどうやって管理しようかー。メッセージのやり取り制御を状態遷移で制御しようかー。とか考えて、open機能を実装した。たぶんできてる。
7 openと同じようなシーケンスなので、メッセージとちょっとやる事変えて簡単にwrite機能を実装できちゃった。
8 writeと同じようなシーケンスなので、メッセージとちょっとやる事変えて簡単にread機能を実装できちゃった。
9 readと同じようなシーケンスなので、メッセージとちょっとやる事変えて簡単にclose機能を実装できちゃった。

応用

これまでmount、open~closeまでさくっと何も考えずに実装してきた。(そういえばunmount実装してないな。まいいか)
全てはドライバとアプリ間のインタフェースを作ることがひとまずの目的だったので、ドライバを作ってみなければ。

というわけでns16550ドライバを作った。
ns16550は所謂、RS-232C、COMポート、シリアルポート、UARTなどと呼ばれているハードウェアで、割りと制御が簡単。

それぞれ16byteの転送バッファと受信バッファがあって、書き込む(VfsWrite)時は転送バッファがフルでなければ1byteづつ書き込んでフルの時は転送バッファ空割り込みが来るまで待つ。読み込む時は受信割り込みが来たときに1byteづつ読み込んでいたデータを返すだけ。

mvfsメインスレッド受信スレッド転送スレッドNS16550VfsReadReqVfsReadRespVfsWriteReq転送バッファ書込転送要求VfsWriteResp転送バッファ空割込み割込み要求転送バッファ読込書込転送バッファ読込書込受信割込み読込受信バッファ書込み読込受信バッファ書込みVfsReadReq受信バッファ読込VfsReadRespmvfsメインスレッド受信スレッド転送スレッドNS16550

MochiKernelのメッセージパッシングはキューがなく、即座にメッセージ受信をしないと仮想ファイルサーバがブロックされてシステムの性能が悪くなってしまうので、メインと受信と転送用に1プロセス3スレッド構成に。
(MochiKernelにスレッド機能なんて無かったので、作った。)

とまぁ、これだけでかなりのネタになるんだけれど、割愛。
⇂がコミットログ。
https://github.com/MasterMochi/drv-ns16550/commit/a09994d07188ec84b663b902f6dbc07509cc44de

本題はこれから。

ttyサーバを作りたいが…

tty「サーバ」って書くと???になるのだけれど、要はttyドライバです。MochiOSではサーバープロセスとしてttyファイルを提供するので「サーバ」にしているだけです。

そんで考えたのだけれど、次のシーケンスで悩みが出てくる。

  1. ユーザアプリがttyサーバに行読込み(cockedモード)
  2. ttyサーバがドライバからデータ読込み
  3. 受信データ無しのため、読込サイズ0で応答。
NS16550ドライバttyサーバユーザアプリ1. VfsRead...Read2. VfsRead...Read3. 受信データ無しの為、サイズ0応答どうやって待ち合わせる…?NS16550ドライバttyサーバユーザアプリ

(シーケンス図では、仮想ファイルサーバは省略。それぞれのインタフェースは仮想ファイルサーバ上で行われる。そのためVfsRead…Readのような形式で記載。上位からはReadを起動し、それを受け取って仮想ファイルサーバから下位へVfsReadが起動される。)

ttyサーバは行データが揃うまでユーザアプリへRead要求を返さない。行データが揃うまで、ドライバから文字を読み続けなければいけないわけだけど、ドライバは受信データが無い(EOF)ので直ぐに読込サイズ0でReadを返す。
(ところが上のコミットではドライバがブロックする設計ミス。。。修正する。)

今、実装済みの機能でこれを実現するには、ttyサーバはドライバへのReadを繰り返すしかない。

NS16550ドライバttyサーバユーザアプリVfsRead...ReadVfsRead...ReadVfsRead...ReadVfsRead...ReadVfsRead...ReadVfsRead...ReadVfsRead...ReadNS16550ドライバttyサーバユーザアプリ

これは、もう、CPU100%一直線。

Select/VfsReady機能を追加する

説明しなくても大体わかると思うけど、selectです。指定したファイルディスクリプタの読み込みまたは書き込みが出来るまで待ち合わせます。
VfsReadyはファイルの読み込みまたは書き込み準備が出来た事を意味する通知。

NS16550NS16550ドライバ仮想ファイルサーバttyサーバSelectレディチェック。読込・書込ともレディでないので待ち合わせ受信割り込み読み込みVfsReadyレディ設定ReadVfsReadデータ & レディ状態読込レディ設定データWriteVfsWriteレディ状態書込レディ設定NS16550NS16550ドライバ仮想ファイルサーバttyサーバ

いちいちSelectで指定した全てのFDに対応するMountプロセスにレディ状態を問い合わせると、メッセージのやり取りが増えて待ち合わせ状態の管理や時間がかかるので、レディ状態は仮想ファイルシステムでも保持する仕様にした。その為、VfsRead応答に最新のレディ状態を含める様に修正する。

以下、メッセージ仕様。

■ Select要求メッセージ

offset size 内容 意味
0x00 4 機能ID 0x0000_0009 Select
0x04 4 タイプ(要求/応答) 0x0000_0000 要求
0x08 4 読込監視グローバルFD数 0~1024 -
0x0C 4 書込監視グローバルFD数 0~1024 -
0x10 4 読込監視グローバルFD[0] 任意 -
読込監視グローバルFD[…]
可変 4 書込監視グローバルFD[0] 任意 -
書込監視グローバルFD[…]

■ Select応答メッセージ

offset size 内容 意味
0x00 4 機能ID 0x0000_0009 Select
0x04 4 タイプ(要求/応答) 0x0000_0001 応答
0x08 4 処理結果 0x0000_0000
0x0000_0001
成功
失敗
0x0C 4 読込レディグローバルFD数 0~1024 -
0x10 4 書込レディグローバルFD数 0~1024 -
0x14 4 読込レディグローバルFD[0] 任意 -
読込レディグローバルFD[…]
可変 4 書込レディグローバルFD[0] 任意 -
書込レディグローバルFD[…]

■ VfsReady通知メッセージ

offset size 内容 意味
0x00 4 機能ID 0x0000_0008 vfsClose
0x04 4 タイプ(要求/応答) 0x0000_0002 通知
0x08 4 グローバルFD 任意 -
0x0C 4 Ready対象 0bit目: read
1bit目: write
読込みレディ
書込みレディ

■ vfsRead応答メッセージ(改造)

offset size 内容 意味
0x00 4 機能ID 0x0000_0006 vfsRead
0x04 4 タイプ(要求/応答) 0x0000_0001 応答
0x08 4 グローバルFD 任意 -
0x0C 4 処理結果 0x0000_0000
0x0000_0001
成功
失敗
0x10 4 読込レディ状態 0x0000_0000
0x0000_0001
非レディ
レディ
0x14 4 読込み実施サイズ 0~24,064 -
0x18 0~24,064 データ 任意 -

■ vfsWrite応答メッセージ(改造)

offset size 内容 意味
0x00 4 機能ID 0x0000_0004 vfsWrite
0x04 4 タイプ(要求/応答) 0x0000_0001 応答
0x08 4 グローバルFD 任意 -
0x0C 4 処理結果 0x0000_0000
0x0000_0001
成功
失敗
0x10 4 書込レディ状態 0x0000_0000
0x0000_0002
非レディ
レディ
0x10 4 書込み実施サイズ 0~24,064 -

実装してみた

ttyプロセスが、select->read->writeを無限に繰り返す様にお試し。COM1で「1234567890Select!」を入力してみた。上のウィンドウは画面でデバッグログを、下のウィンドウはCOM1。端っこ切れてる。。
enter image description here
深く説明はしないけど、まぁCPU100%にならずに読込み待ちできたって感じです。

ここで問題発生

これまで、突貫で適当に作りすぎてて、機能毎に複数の要求を扱えない。
なので、ttyファイルをReadするとその先のドライバファイルのReadが行えない状況に。。。

driver仮想ファイルサーバttyサーバuser「/com1」をMount「/ttyS0」をMount「/ttyS0」に対してReadVfsRead「/com1」に対してReaduserからのReadを実行中なので無理VfsReaddriver仮想ファイルサーバttyサーバuser

直さねば。全体的に大改造なので、次回の更新はいつになるかな。

コメント

このブログの人気の投稿

プライバシーポリシー

git@よく使うコマンド早見表