[OSASK 4273] コンソールAPI(1).

  こんばんは、川合です。

  OSASKのコンソールAPIの概略について書きます。

  結局のところ、コンソールAPIはファイル周りのファンクションの追
加ということに尽きます。フィルターなどは標準入力から取り込んで、
標準出力へ出すだけです。後はコマンドラインオプションを取り込める
ことくらいです。標準入力や標準出力は普通のファイルだったりするこ
ともありますが、コンソールや他のタスクとパイプでつながっているこ
との方が多いでしょう。ということで、ここからはそのパイプについて
です。

  OSASKのAPIにもパイプのサポートがあります(今はありませんが、こ
れからつけます)。しかしパイプは特別な仕組みではなく、ただのモジ
ュール(ファイル)です。今までと同じように、普通にメモリマップト
ファイルでアクセスします。

  パイプへのリードアクセスを考えてみましょう。今までのファイルア
クセスの方法だけではどこまで出力されているのか、それは分かりませ
ん。パイプなんですから、徐々に出力が付け足されていくわけです。・
・・したがって今までのファイルアクセス方法でオープンした場合、パ
イプの出力側のタスクが全て出力しおわるまで、オープンは完了しませ
ん。これはちょうどMS-DOSの一時ファイル方式と同じになります。

  これでは不便ですので、これから新しいモジュールアクセスファンク
ションが追加されます。これらを使うなら、出力側が全て出しおわらな
くても、パイプをリードできます。

  追加されるファンクションは以下の通りです。

(1)アクセスロック要求 (リード一時・リード確定・リードライト)
(2)ロック開放
(3)アクセス可能範囲通知 (リード・ライト、一時・確定)
(4)通知シグナル設定
(5)通知シグナル送信 (リード・ライト・サイズ変更、一時・確定)

  UNIXなどではファイルにロックをかけることができますが、OSASKで
はモジュール全体にロックをかけるばかりではなく、部分的にロックを
かけることができます。

  また書きおわった領域に対しても、もうその領域は書き換えるつもり
がないのか、それともまたその領域を書き換えるかもしれないのか、そ
の意志を示す必要があります。

  一方、リード側も読み終わった領域に対して、またその範囲を読み込
むつもりがあるのか、それとももう読むつもりがないのか、意志を示す
必要があります。システム側としては、今後誰からも相手にされないと
確定した領域については、どんどん捨てます。

(例 - 1)

  さて、では、"hello, world"と標準出力に出力するためのプログラム
を考えましょう。

  面倒なことを極力減らすという観点に立てば、スロット0x200は標準
出力に割り当てられているので(どのスロットを何に割り当てるかはリ
ンク時に決めます)、そこへ該当文字列を出力することだけを考えます
。

  スロット0x200を13バイトにリサイズして、適当にマップし、"hello,
 world\n"を書き込みます。そしてタスクを終了すれば終わりです。こ
れが一番簡単な方法です。問題ありません。なお、スロット0x200は起
動時にオープンされているので、プログラム内でオープン処理をする
必要は全くありません。

(例 - 2)

  今度は同じ"hello, world"をもうちょっとややこしい手順で出力して
みます。

  まずスロット0x200に対して追加リサイズ権とオフセット0〜12に対し
てのリードライト権を要求します(上記の(1))。この時ロック解除要
求に応答するかどうかを設定できるのですが、ここでは解除要求に応じ
ないとします。権利を獲得できるとシグナルが来ることになっているの
で、それを待ちます。シグナルがきたらリサイズしてマップして書き込
んでタスク終了です。ロックを開放する必要はありません。

  (例 - 1)ではこのようなロック要求をしませんでしたが、それは起動
時に簡易オープンするようにリンクで指定しておいたからです。(例 - 
2)では拡張オープンなので、自分でロックを制御します。なお、タスク
が終了するとファイルはクローズされますし、ロックは全て解除されま
す。

(例 - 3)

  標準入力から取り込んだ内容にたいしてtoupper()して出力するフィ
ルターを例に取ります。まずは、入力も出力も簡易オープン版から。

  スロット0x200が入力で0x210が出力になっているとしましょう。簡単
です。0x200のサイズを取得して0x210をリサイズし、どちらもマップし
て、あとはひたすらtoupperしながらコピーするまでです。終わったら
終了です。

  この例ですと、このフィルターをコンソールで実行した場合、コンソ
ールでの入力が終わらないと出力が始まりません。

abcdefg
hijklmn
^z
ABCDEFG
HIJKLMN

のようになります。これはコンソールでの入力が終わらないと入力側の
パイプのオープンが完了せず、タスクが起動できないからです。こうい
う欠点が簡易オープンにはあります。

(例 - 4)

  今度は(例 - 3)の拡張オープン版です。

  まずスロット0x200に対して通知シグナルを設定します。リード確定
領域変更についてです。そしてとりあえずスリープです。

  シグナルがきたら、それは間違いなくリード確定領域変更シグナルな
ので、仕事を始めます。まず確定した領域をシグナルから読み取り、0x
200と0x210の両方にその範囲でロックをかけます(リード確定ロックと
リードライトロックと追加リサイズロック)。そして、0x210側のサイ
ズが足りなければ変更し、マップしてtoupperしながらコピーします。
終わったら、ロックを解除し、0x200と0x210の終了した範囲にはリード
ライト確定完了のシグナルを通知し、そしてまたリード確定領域変更シ
グナルを待ちます。

  これで、

abcdefg
ABCDEFG
hijklmn
HIJKLMN
^z

というふうになります。

(例 - 5)

  さらに(例 - 4)を改造して、リード一時確定領域変更シグナルにも対
処すれば、もっと面白いことになります。一時確定というのは、出力側
が「とりあえず出力するけど、この部分はあとで変えるかもしれない」
という意味です。この場合、このフィルターは一時確定ライト完了で応
じることになります。

  この場合でも、もちろん普通のフィルターとして使う分には変わりま
せん。しかし、入力をコンソールにして、出力先を一時確定対応teditc
にするとすごいことになります(パイプも普通のファイルとして扱える
のでテキストエディタで開けます。teditcをクローズするとパイプはな
くなってしまいますが)。入力した文字がEnterを押す前からteditcの
方に大文字化して出力されるのが分かるでしょう。サイズもコンソール
でのキー入力にあわせて小刻みに変化します。

  なんなら入力側だってteditcでいいのです。パイプはファイルです。
何もコンソールに直接入力するだけが能ではありません。teditcなら前
の行に戻って編集することもできますし、切り貼りもできます。コンソ
ール入力よりずっといいですね(笑)。

  テキストエディタを2つ開いて、その間をフィルターで挟む、なんて
ことができるOSが他にあるでしょうか?役に立つかどうかは別にして、
破格の面白さだと僕は思います。

  結局、パイプとファイルが統合されているわけです。

---

  以上のやり取りは、とても面倒だと思われたかもしれません(僕は思
いました)。しかし心配することはありません、なんならライブラリを
使えばいい訳です。fgetcやfputcでやることもできるでしょう。一時確
定には対応できませんが、普通のフィルター程度の機能ならこれでOKで
す。

  なお、以上のややこしいやり取りはパイプのみならず普通のファイル
にもできます。これにより、teditcで書き換えたら即座に同じファイル
のbeditcに反映した、なんていうことも可能になります(どちらも拡張
オープン版に書き直さなきゃいけませんが)。また今のteditcとbeditc
はどちらも簡易オープンなので、同時に同じファイルをオープンするこ
とはできなくなります(オープンが完了しないか、もしくはエラーシグ
ナルが返される)。

  それでは。

--
    川合 秀実(KAWAI Hidemi)
OSASK計画代表 / システム設計開発担当
E-mail:kawai !Atmark! imasy.org
Homepage http://www.imasy.org/~kawai/


ML番号でジャンプ
ML単語検索