FENIX Ver0.2 Copyright (C) 1991-1998 S.Uchida
fsh Ver0.2 Copyright (C) 1991-1998 S.Uchida
FENIXは、プログラムをオブジェクトという形で管理します。 オブジェクトとは、メモリ上に存在するプログラム・データの単位のことです。 ディスクで言えばファイルに相当し、ファイルと同様に名前をつけて管理されています。 最大16個のオブジェクトを持つことができますが、その内の1つはシェルですので、ユーザーが利用できるのは15個です。
オブジェクトには以下の3つのタイプがあります。
bin ... 直接実行可能なバイナリプログラム
dat ... 単なるデータ
txt ... テキスト
MZ−2500は8KB単位でメモリが分割され、自由にマッピングを行うことができますが、オブジェクトはこのメモリブロック(MB)を単位として構成されます。 どんな小さなオブジェクトでも、最低1MB・8Kバイトを占めることになります。
各オブジェクトは複数のMBを持つことができますが、それらのMBにアクセスする際にその実際のMB番号を知る必要はありません。 FENIXは各オブジェクトに対してローカルなMB番号を与えます。
例えば、6個のMBを持つオブジェクトがあった場合、それらには実際のMB番号とは関係なく、0〜5というMB番号が与えられます。 これをローカルMB(LMB)と呼びます。 このLMBを用いてマッピングなどを行います。
さらに、EMMを装着している場合、EMM上にLMBを確保することができます。 EMMは640Kバイトありますから、640/8=80ブロック使用可能です。 (実際はRAMディスクとしても使用することからこれより少なくなります)
これに伴い、以下のようにMB番号が拡張されます。
00H〜0FH メインRAM(標準)
10H〜1FH メインRAM(拡張)
20H〜27H VRAM(標準)
28H〜2FH VRAM(拡張)
30H〜7FH EMM
しかしEMM上にLMBがあると、メモリ上にマッピングすることができません。 そこで、EMM上のLMBをマッピングする必要が生じた場合にはメモリスワップを行います。
本体内のMBの内容と、マッピングするEMM内のMBの内容とを交換し、その本体内のMBを新たにそのオブジェクトのLMBとします。 LMBは実MB番号とは無関係なので全く支障はありません。 また、交換に使用する本体内のMBの選択はLRU(Least Recently Used)リストを用いて行っています。
メモリスワップは自動的に行われます。 従ってユーザーは基本的に気にする必要はないのですが、注意しなければならないことがあります。
メモリスワップが生じると、本体内のメモリの内容が変化します。 そのためメモリマッピングは必ずFENIXのファンクションを用いなければならないのですが、割り込み、エラー処理などで強制的にマッピングの変更が行われる場合があります。 この場合、実MB番号を用いたマッピングが行われますが、その内容は保証されません。
従って、エラー処理などでシステムによってマッピングされるMBは、FENIXのファンクションによってスワップ不可にしておかなければなりません。 ただし、システムが使用しているMBはFENIXの管理外ですのでスワップされず、気にする必要はありません。
なお、1つのオブジェクトの最大サイズは512KBです。
通常ユーザーはシェルからプログラムを起動しますが、それには2つの場合があります。
実行するファイルをオブジェクトとしてロード
→ オブジェクトを起動する。
→ 実行が終わったらオブジェクトを消去する。
こうして従来のOSと同様に動いているように見せかけているのです。
本来オブジェクトは、実行が終わったからといって自然に消去されるものではありません。 つまりFENIX上で動くプログラムは全て、広い意味で「常駐」すると言えるのです。
このことを利用することによって、オブジェクトを単なるプログラムにとどまらせず、様々な機能を持たせることが可能となります。 以下は、それに関する用語説明です。
そこで、オブジェクトが自分自身の書き込み許可を取り消すことによって(オブジェクト管理テーブルの説明を参照して下さい)ファイルから起動した場合でもシェルに消去されずに済みます。
こうすることで自ら常駐するオブジェクトを常駐オブジェクトと名付けます。
この、自分自身を消去した状態というのは、FXC .KILLOBJ を実行してもメモリマッピングが変更されるわけではない、というところから可能な状態です。
しかしこれは、オブジェクトとして死んでしまった(メモリも解放されている)プログラムが動いている危険な状態です。
この状態をゾンビオブジェクトと名付けます。ゾンビオブジェクトは速やかに呼び出されたシステムに帰り、迷わず成仏しなければなりません。
FENIXでは以下の種類のTSRをサポートしています。
以下の7個の割り込み源をサポートしています。
PIOと優音以外はIOCSが使用していますので、不用意に使用するとシステム自体が動かなくなってしまいます。
TSRオブジェクトは専用のFXCを用いて登録して使用します。 詳しくは Technical manual を参照して下さい。
元々異なる管理方式で扱われているファイルを統一的に扱うために多少制限があります。 OBJ,BTX は特に注意が必要です。
OBJ,BTX はその管理方式の都合上、セーブ時にセーブサイズを指定しなければなりません。そして、書き込み時にもEOFチェックが必要です。
さらにオープンした時点で既にファイルが作成されているので、close/killファンクションを用いてkillすることができません。
(管理テーブルの構成を見てもらえばわかりますが、OBJ,BTX のアクセスにはデバイス名とレコード番号に関する情報しかありません。ファイル名の情報がないのでkillできないのです)
このように制限が多いので、OBJ,BTX は統一アクセスによる書き込みは不得手です。
BSD,BRD に関してはIOCSに操作ファンクションがあり、LUを用いてアクセスできますが、OBJ,BTX に関してはそういったものはありません。 そこで、FENIX内部でLUを用意しています。 IOCSで用いられるLUは0〜127なので、128以上をFENIXのLUとしています。この番号は固定で、128〜143の16個が使用可能です。
FENIX上でファイルを扱う場合、ユーザーはLUを指定する必要はありません。 ファンクションの説明を見てもらえばわかりますが、LUはFENIXによって与えられます。
オブジェクトもこの統一アクセスを用いて作成することができます。 インタフェイスが全く同じなのでファイルと同様に扱えます。
例えばVRAM上にプログラムを乗せても走りませんし、逆に単なるデータであればメインRAMにしかマッピングできないというのでは非効率的です。 VRAMが余っているのに、単なるデータがメインRAM上にあるために別のプログラムを動かすことができないというのでは困るでしょう。
そのため、LMB単位でどの種類のメモリにマッピングすることができるかを設定することができます。 これがマッピングモードというもので、以下の3+1種類があります。
モード0 main のみ ( main,EMM,VRAM )
モード1 main 優先 VRAM も可 ( main,VRAM,EMM )
モード2 VRAM 優先 main も可 ( VRAM,main,EMM )
モード3 VRAM 優先 main も可 ( EMM,VRAM,main )
括弧内は確保されるメモリ種別の優先順位を表しています。 必ずしも目的の種類のメモリが確保されるとは限らないのですが、マッピングする際にメモリ種別が合わなければスワップしますのでアプリケーション側で配慮する必要はありません。
プログラムがあるLMBは当然モード0で確保しなければなりません。
モード3は FXC .GETMB でのみ使われるモードです。 マッピング可能メモリはモード2と同じなのですが、確保する際には極力メインRAMを避けるように設定されています。
これは統一アクセスを用いる際に有効です。 統一アクセスではオブジェクトを読み書きする場合にマッピングを行いませんから、あらかじめメインRAMを避けて確保することによってスワップによるタイムロスを避けることができます。
bin ... モード0
dat ... モード1
txt ... モード3
これはそのオブジェクト自身のタイプとは無関係です。 従って、既に存在するオブジェクトをそのタイプと別のタイプでオープンすることでオブジェクトの一部のLMBを異なるモードにすることができます。
Ver0.2 では、TSR処理ルーチンをスタック上に置いてあるため、現在 1A80H〜1F??H の1Kバイト強の領域が利用可能です。
そのためには、FENIXがあるディレクトリ(通常ルートディレクトリ)に .fenix というBSDファイルを作成します。
例えば
fsh00 /bin/shell01
という2行が .fenix に書かれているとすると、FENIXを起動した時には1行目に書かれている fsh00 というファイルをシェルとしてロードします。 起動時にファンクションキーの2番(F2)を押しておくと、2行目の /bin/shell01 をシェルとしてロードします。 .fenix のn行目がファンクションキーn番に対応して、シェルが決定されます。
つまり、
☆ .fenix がある場合
☆ .fenix がない場合
カレントディレクトリから fsh をロードする。 ないと暴走しますので、"FENIX" と同じディレクトリに必ず "fsh" をおいて下さい。
その他、
アプリケーション側でエラートラップしても構いません。 シェルは1コマンド実行するごとにエラー処理を初期化しますので、処理アドレスやマッピングデータを元に戻さなければならないということはありません。 ただし、エラーマッピングはFENIXを介さずに行われますので、マッピングするLMBはスワップ不可にしておくのを忘れないようにして下さい。
FENIXで生じるエラーは、IOCSのものを除けば現在2つだけです。 エラーコードは71〜を使用しています。
これらのエラーは FXC .ERRMSG で表示されます。
71 Permission denied. オブジェクトのアクセス許可がありません。 r:読み出し許可、w:書き込み許可、x:実行許可の3つがあります。
72 Object full. オブジェクトが一杯で新規オープンできません。
このファンクションでは73〜はユーザー用になっていますが、シェルのエラー処理では73〜をシェルのエラーコードとして使用しています。
シェルのエラー処理でユーザーのエラーメッセージを表示したい場合は、エラーコード127を発生させてください。
( LD A,127 ,DE にメッセージへのポインタを入れ、JP 00ACH )
ただしエラーマッピング後にメッセージがメモリ上にないといけませんので、メッセージはコモンエリアに転送しておいた方がいいでしょう。
シェルで生じるエラーは以下の通りです。
シェルのエラーコードは今後増加するかもしれません。
73 Too many arguments. コマンドの引数が多すぎます。 少ない場合は、普通そのコマンドの使用法が簡単に表示されます。
74 Ambiguous. ワイルドカードで指定されたファイル/ディレクトリが特定できません。
75 No match. ワイルドカードにマッチするファイルがありません。
76 Not shell script. 実行しようとしたtxtオブジェクトがシェルスクリプトではありません。(最初の文字が # ではない)
A オブジェクトID引数はシェルによって解釈されたワードリストです。 各ワードは 00 を分割コードとして構成されています。 そしてワードリストの先頭にはワードの数が格納されています。 第1ワードはコマンド名です。
DE 引数へのポインタ(コモンエリアの BUF2)
例
最終ワードの次には2つの 00 が格納されます。save fsh EMM: と入力した場合 03 73 61 76 65 00 66 73 68 00 45 4D 4D 3A 00 00 s a v e f s h E M M : ↑ ↑ ↑ ↑ ↑ ワード数 区切り 区切り エンドコード
シェルのメタキャラクタなどは解釈済みですが、ワイルドカードは展開されない場合があります。 それは複数のファイルにマッチする場合、及びマッチするファイルがない場合です。
例えば "f*" にマッチするファイルが "fsh" だけの場合、"fsh" と展開されます。 しかし "fsh0","fsh1" などの複数のファイルにマッチすると、ワイルドカードのままワードリストを構成します。
UNIXであればファイルリストが展開されますが、MZの場合256バイトのバッファを用いていますので無理です。 しかしその代わりにワイルドカードの展開をカーネルのファンクションにしています。 アプリケーションはなるべくワイルドカードに対応するようにしてください。
また、マッチするファイルがない場合、その処理をアプリケーション側で行うことができるように、ワイルドカードのまま渡すようになっています。
1つのMBあたりに2バイトが割り当てられています。
また、MB00に対するテーブルの位置に対して、
+0 ... bit0〜5 リストの前のMB bit7 スワップ許可(1で禁止) +1 ... bit0〜5 リストの次のMB
-4 ... メインRAMのLRUが格納されています。
-3 ... メインRAMのMRU
-2 ... VRAMのLRU
-1 ... VRAMのMRU
オブジェクトの先頭MBはオブジェクト管理テーブルに記述されています。
+0 ... bit0〜6 次のLMBのMB番号(最後のMBならば0) bit7 使用中なら1、未使用なら0 +1 ... bit 7,6 00 ; 通常RAM(オブジェクトが所有) 01 ; 未装着 10 ; カーネルが所有 11 ; IOCS等が使用(FENIXの管理外) bit 5,4 01 ; main のみ 10 ; VRAM / main 11 ; main / VRAM bit0〜3 そのMBを所有するオブジェクトのID
2バイト目のデータは、そのMBがフリー(1バイト目の bit 7 = 0)の場合は不定となります。(正確に言うと解放される前の値を保持している)
bit 5,4 はオブジェクトのLMBとしてマッピングするときのモードを示しています。
ファイル(OBJ,BTX)の場合
オブジェクトの場合
+0 ... bit 7 1 でテーブル使用中 bit 6 0 (ファイルである) bit 2 1 で read 可能 bit 1 1 で write 可能 bit 0 1 で EOF +1 ... 未使用 +2 〜 +7 ... デバイス名(max 3byte)+チャンネル+":"+00H +8 , +9 ... 次にアクセスされるレコード +10 ,+11 ... 最終レコード(読み出し用)
オブジェクトの場合のブロックとは、256byte単位のものです。 1つのLMBに 0 〜 31 の32ブロックがあります。
+0 ... bit 7 1 でテーブル使用中 bit 6 1 (オブジェクトである) bit 2 1 で read 可能 bit 1 1 で write 可能 bit 0 1 で EOF +1 ... オブジェクトID +2 ... オープンモード(LMB確保時のモード) 0 ... main のみ(bin) 1 ... main/VRAM(dat) 3 ... VRAM/main(txt) +3 〜 +5 ... 未使用 +6 ... オープン時の +8 の値 +7 ... オープン時の +9 の値 +8 ... 次にアクセスするLMB +9 ... 次にアクセスするブロック +10 ... 最終LMB(読み出し用) +11 ... 最終ブロック(読み出し用)
サイズは統一アクセスによって書き込まれるものです。 FXC .GETMB や FXC .RELMB では変化しません。
+ 0 ... タイプ ( 0...未使用 , 1...bin , 2...dat , 3...txt ) + 1 〜 +17 ... 名前 (End code 00H) +18 ... 属性 bit 0 exec permission bit 1 write permission bit 2 read permission (それぞれ1で禁止) bit 3 1...オープン中 +19 ... 先頭MB番号(0FFH...確保されていない) +20 , +21 ... サイズ(+20...LMB , +21...block) +22 , +23 ... 先頭アドレス +24 , +25 ... 実行アドレス +26 〜 +31 ... 実行時マッピング(バンク2〜7にマップするMB番号)
実行時マッピングは正確には FXC .EXECOBJ に渡されるデータです。 フォーマットは FXC .EXECOBJ の説明を参照して下さい。
+ 0 オブジェクトID + 1 〜 + 6 マップ + 7,+ 8 コールアドレス
+ 0 オブジェクトID + 1 〜 + 6 マップ + 7,+ 8 コールアドレス + 9,+10 コモンエリアタイマテーブルのアドレス
+ 0 オブジェクトID + 1 〜 + 6 Aポート処理時マップ + 7,+ 8 Aポート処理時コールアドレス + 9 〜 +14 Bポート処理時マップ +15,+16 Bポート処理時コールアドレス
+ 0 オブジェクトID + 1 〜 + 6 ch.Bトランスミッタバッファエンプティ処理時マップ + 7,+ 8 ch.Bトランスミッタバッファエンプティ処理時コールアドレス + 9 〜 +14 ch.B外部/ステータス割り込み処理時マップ +15,+16 ch.B外部/ステータス割り込み処理時コールアドレス +17 〜 +22 ch.B受信キャラクタアベイラブル処理時マップ +23,+24 ch.B受信キャラクタアベイラブル処理時コールアドレス +25 〜 +30 ch.B特殊受信状態処理時マップ +31,+32 ch.B特殊受信状態処理時コールアドレス +33 〜 +38 ch.Aトランスミッタバッファエンプティ処理時マップ +39,+40 ch.Aトランスミッタバッファエンプティ処理時コールアドレス +41 〜 +46 ch.A外部/ステータス割り込み処理時マップ +47,+48 ch.A外部/ステータス割り込み処理時コールアドレス +49 〜 +54 ch.A受信キャラクタアベイラブル処理時マップ +55,+56 ch.A受信キャラクタアベイラブル処理時コールアドレス +57 〜 +62 ch.A特殊受信状態処理時マップ +63,+64 ch.A特殊受信状態処理時コールアドレス
+ 0 オブジェクトID + 1 〜 + 6 マップ + 7,+ 8 コールアドレス
これを見ればわかるように、同一割り込み源から複数の割り込みが生じる場合でも各割り込みに対して異なるマッピングを行うことが可能です。 .TSRON では、オブジェクト管理テーブルのマッピングデータを実MBに変換してこのテーブルに登録します。
そのため、例えばSIOの場合、8個の割り込みのマップデータ全てが同一のものとして登録されます。 しかし、一度登録した後 .TSRTAD を用いてマップデータを書き換えることにより、処理に応じたマッピングが可能となります。
オーナーオブジェクトIDは .KILLOBJ でしか使われていません。
+0 オーナーオブジェクトID +1〜+2 領域開始アドレス +3〜+4 領域終了アドレス