If you are still using the old URL (datacrystal.romhacking.net), please update your bookmarks! The old URL may stop working soon.
The current URL is datacrystal.tcrf.net.
The current URL is datacrystal.tcrf.net.
X68k/V2FUNC
Jump to navigation
Jump to search
This is a sub-page of X68k.
プログラマーズマニュアル 第八章 Human68k ver.2.0 の新機能 ============================================================================== 8.1 バックグラウンド処理 Human68k ver.2.0 では、複数のユーザプログラムを並列実行できる「バックグラウ ンド処理」をサポートしています。 この機能により、X68000 をネットワークのファイルサーバとして動作させる、ある いは、TIMER コマンドのように指定時間に ADPCM や TV をコントロールする、といっ た処理が Human68k の管理下でできるようになります。 ここでは、バックグラウンド処理の概要について解説します。 バックグラウンド処理プログラムは、ここで解説する DOS コールを組み合せて作成 します。 8.1.1 プロセスとは Human68k の管理下で実行されるプログラムは、「プロセス」と呼ばれます。外部記 憶装置(フロッピーディスクなど)に格納されているプログラム・ファイルを Human68k がメモリ上にロードすると、それはプロセスとなります。 各プロセスには他のプロセスとは独立した環境が用意されます。 プロセスは DOS コールの exec($ff4b)を実行するごとに、一個ずつ増加します。 この時、exec($ff4b)を実行したプロセスを親プロセス、exec($ff4b)によりディスク からメモリへロード・実行されるプロセスを子プロセスと呼びます。 つまり、COMMAND.X 上からアプリケーションを実行した場合、COMMAND.X を親プロセ ス、そのアプリケーションを子プロセスと呼びます。 メモリ上に複数のプロセスを同時に存在させることは可能ですが、これまで、各プロ セスを並列に実行する機能は Human68k に用意されていませんでした。 しかし、Human68k ver.2.0 より、次に説明する「スレッド」を利用することにより、 各プロセスを並列に実行することが出来るようになりました。 8.1.2 スレッドとは スレッドとは、メモリ上でプログラムが実行されるときの制御の流れと言えます。 つまり、並列に実行されているプログラムの一つ一つがスレッドなのです。実際には CPU は同時に一つの命令しか実行できないので、Human68k が各スレッドの実行を高速 に切り替えることで、見かけ上並列に実行されているように制御します(下図参照)。 スレッド1 →‥‥‥→‥‥‥‥→ スレッド2 ‥─→‥‥─→ スレッド3 ‥‥‥→‥‥‥─→ ──────────→時間 →は、そのスレッドが実行中であることを表わしています。 一つのプロセスを複数のスレッドに分割して並列に実行させることも出来ますが、通 常は一つのプロセスを一つのスレッドとして割り当てるべきです。なぜなら一つ一つの プロセスから複数のスレッドを実行した場合、どれか一つのスレッドが環境を変更した 場合、他のスレッドの環境も変更してしまうからです。 スレッドは、DOS コールの open_pr($fff8)を実行することで、システムに登録され ます。open_pr($fff8)を実行するごとにスレッドは一個ずつ増加します。 8.1.3 スレッドの状態 スレッドの状態には、実行状態であるアクティブ状態と、待機状態であるスリープ状 態があります。 あるスレッドが、他のスレッドの実行要求があるまで何も実行する必要のない場合に は、スリープ状態になることにより、要求があるまで待機します。 そうすることで実行時間を余計に消費することが無くなり、全体の実行速度が遅くな らずに済みます。 そのための DOS コールが sleep_pr($fffc)です。 この DOS コールでは、スリープ状態になっている時間を指定することが出来ます。 8.1.4 スレッド間通信 複数のスレッド間で、情報の受け渡しを行う場合、無秩序に情報の書き込みや読み込 みを行うと、複数の書き込みが衝突したり、書き込みの途中で読み込みが行われ、正し く情報が受け渡しできない場合があります。 そのために、情報の受け渡し(通信)を行うための DOS コールが用意されています。 それが、DOS コールの send_pr($fffd)です。 また、この DOS コールでは、情報の通信以外にも、スリープ状態のスレッドを、ア クティブ状態にすることが出来ます。 また、コモンエリアを使って、スレッド間で通信を行うことも出来ます。これについ ては、「8.2 コモンエリア」で説明しています。 8.1.5 スレッドの区別 複数のスレッドそれぞれには、固有の ID と、プログラム名が割り当てられます。 この ID や名前によって、どのスレッドからどのスレッドへ情報通信が行われるのか を指定します。 したがって、各スレッドの ID や名前を取得することが必要です。 そのための DOS コールが get_pr($fffa)です。 また、この DOS コールでは、各スレッドの詳細な情報を取得することが出来ます。 8.1.6 並列処理と実行権 並列処理とは、一定の時間間隔でスレッドの実行を切り替えることによって見かけ上、 同時にプログラムが実行されているように処理することを言います。 あるスレッドが一定時間実行している状態のことを、そのスレッドが実行権を持って いると表現します。 この時、あるスレッドがスーパーバイザ状態になっていると、DOS コールを行うなど しない限りスレッドが切り替わりません(このような状態を「実行権の占有」と言います)。 このような場合、他のスレッドの処理が停滞してしまうので、これを防ぐために一定 の周期で実行権を放棄しなければなりません。 そのための DOS コールが change_pr($ffff)です。 8.1.7 スレッドの破棄 並列処理中に何らかの理由によって、特定のスレッドが不必要になる場合があります。 また、プロセスの終了時には、そのプロセスが生成した全てのスレッドを破棄しなけ ればなりません。 そのための DOS コールが kill_pr($fff9)です。 スレッドを破棄する場合、スレッドを無秩序に破棄してはいけません。 無秩序に破棄を行うと、システムで回復不可能で致命的な異常が発生する場合があり ます。自分以外のスレッドを破棄する場合は、破棄したいスレッドに破棄要求を行いま す。 その後、すみやかに実行権を放棄して破棄したいスレッドに実行権を渡します。 破棄要求を受け取ったスレッドは、それが受け入れられる要求であれば、要求にした がって破棄を行います。 受け入れられない要求であれば、その要求を捨てた後、実行権を放棄します。 その後、要求を発行したスレッドに実行権が戻ってきた時点で、要求したスレッドの 詳細情報の取得 get_pr($fffa)を試みます。 取得が成功すれば、破棄できなかったことを示します。 失敗すれば、破棄できたことを示します。 自分自身のスレッドを破棄したい場合は、まず永久ループ状態に入り、他のスレッド からアクティブ状態にされるまで待機します。アクティブ状態にされたら速やかにスレ ッドを破棄します。 他のスレッドは、どれかのスレッドが上記のような待機状態になっている可能性があ るので、定期的に通信を行います。 そしてこの時、通信に失敗したならば、そのスレッドが自分自身の破棄を行ったこと を知ります。 8.1.8 環境の競合 マルチスレッドとは、一つのプロセス上で複数のスレッドが実行されている状態を言 います。 マルチスレッド実行状態では、全てのスレッドは、同一の環境で実行されます。 同一の環境で実行されるということは、プロセスが同一であり、メモリや、DOS のエ ラー処理、その他全て同じ環境で実行されていることを意味しています。 したがって、複数のスレッド内でメモリの確保を行ったり、他のスレッドを残した状 態で、DOS コール exit($ff00)で終了したり、CTRL-C や DOS のエラーアボートで終了 したりしてはならないということです。 標準状態では、CTRL-C や DOS のエラーアボート処理で終了するようになっています ので、それらの処理をそれぞれのプロセスで処理することが必要になります。 8.1.9 環境の競合 ファイルや画面やキーボードなど入出力が行われるデバイスでは、各スレッドでの競 合の発生を防止する必要があります。 ファイル資源の競合を防ぐには、ファイルシェアリングやファイルロックのための DOS コールが用意されています。 画面やキーボードについては、スレッドによって競合しないように注意して下さい。 メモリ資源については、各スレッドで、同一なメモリ管理上で動作します。スレッド 単位でメモリ管理を分割するための DOS コールを使用しない場合には、無秩序にメモ リの確保、解放などを行ってはなりません。 8.1.10 子プロセスの起動 あるスレッドが子プロセスを実行する場合、子プロセスから戻って来た直後で、一度、 実行権の放棄を行って下さい。 これによって、他のスレッドがそのことを知ります。 ============================================================================== 8.2 コモンエリア 親プロセスと子プロセス、あるいは二つの子プロセスとの間でデータのやり取りを行 うには、いくつかの方法があります。 例えば、 ・子プロセスに渡されるコマンドラインにパラメータを設定する ・親プロセスと子プロセスで共通の環境エリアを設ける ・ユーザプログラム中で共有メモリ領域を確保し、通信を行う しかし、このような方法には以下に示す欠点があります。 ・プロセス間で相互に通信するのが難しい ・やり取りされるデータの形式や大きさが限定される ・ユーザプログラムにかかる負担が大きい Human68k ver.2.0 では、このプロセス間のデータのやりとりを OS レベルでサポー トしました。 ユーザプログラムから DOS コールを呼び出すとこにより、OS が「コモンエリア」と 呼ばれる、各プロセス間で共有されるメモリ領域を確保し、アクセスされる時の排他 制御などを行います。 なお、コモンエリアはプロセス間はもちろん、スレッド間でも利用することが出来ます。 8.2.1 コモンエリアの機能 コモンエリアに関して、以下に示す機能があります。 ・コモンエリアの確保および削除 ・コモンエリアに対するデータの読み込み/書き込み ・コモンエリアのロックおよびロック解除 コモンエリアを確保する時には名前をつけます。 アクセスやロックの際には、コモンエリアにつけられた名前を指定します。また、名 前の他にも、アクセスやロックの対象となる部分も指定します。つまり、「????という 名前のコモンエリアの先頭から??バイトより??バイト分だけ読み込む」ということが出 来ます。 またコモンエリアは複数個設けることができ、その上限はメモリ容量に依存します。 8.2.2 コモンエリアの利用方法 コモンエリアを利用するには、DOS コールの common($ff85)を用います。 以下の解説は、本マニュアルの DOS コール common の項を参照して下さい。 ①コモンエリアの確保 common(2,NAME,POS,BUFFER,LEN) NAME :新たに確保するコモンエリアにつける名前 POS :初期化するデータを書き込む先頭からの位置 BUFFER :初期化するデータが格納されているアドレス LEN :初期化するデータのバイト数 リターン値は、実際に書き込んだデータのバイト数、またはエラーコード ②コモンエリアの検索 common(0,NAME) NAME :検索するコモンエリアの名前 リターン値は、コモンエリアが見つかった場合はそのバイト数、見つからなければエ ラーコード ③コモンエリアからの読み込み common(1,NAME,POS,BUFFER,LEN) NAME :対象のコモンエリアの名前 POS :読み込むデータの先頭からの位置 BUFFER :読み込むデータを格納するアドレス LEN :読み込むデータのバイト数 リターン値は、実際に読み込んだデータのバイト数、またはエラーコード ④コモンエリアへの書き込み common(2,NAME,POS,BUFFER,LEN) NAME :対象のコモンエリアの名前 POS :書き込むデータの先頭からの位置 BUFFER :書き込むデータが格納されているアドレス LEN :書き込むデータのバイト数 リターン値は、実際に書き込んだデータのバイト数、またはエラーコード ⑤コモンエリアのロック common(3,NAME,POS,ID_PSP,LEN) NAME :対象のコモンエリアの名前 POS :ロックする領域の先頭からの位置 ID_PSP :ロックする時につけるID LEN :ロックする領域のバイト数 リターン値はエラーコード 注:ロックを行うと、ID_PSPをもつプロセスやスレッドの他からはアクセス出来なくな ります。 ⑥コモンエリアのロック解除 common(4,NAME,POS,ID_PSP,LEN) NAME :対象のコモンエリアの名前 POS :ロック解除する領域の先頭からの位置 ID_PSP :ロックする時につけたID LEN :ロック解除する領域のバイト数 リターン値はエラーコード ⑦コモンエリアの削除 common(5,NAME) NAME :対象のコモンエリアの名前 リターン値はエラーコード ============================================================================== 8.3 ファイルシェアリングとファイルのロック 複数のスレッドが並列に実行される場合、注意すべき事として、ファイルの取り扱い があります。 例えば、あるスレッドがあるファイルをオープンして書き込みを行っている間に、別 のスレッドがそのファイルをオープンしてアクセスする、という状況が考えられます。 その為、Human68k ver.2.0 では「ファイルシェアリング」という機能を新たに付加 しました。 ファイルシェアリングは、ファイルの共有を許す機能です。 また、ファイルをオープンする時に、他からのアクセスを禁止するファイルのロック という機能も加えられました。 これらの機能によりネットワーク環境が実現可能となりました。 8.3.1 ファイルシェアリングの使用方法 シェアリングの指定は、ファイルをオープンする時に指定します。 ファイルのオープンは、DOS コールの open($ff3d)を使用します。 以下の解説は、本マニュアルの DOS コール open の項を参照して下さい。 open(NAMEPTR,MD) NAMEPTR :文字列(ファイル名)へのポインタ MD :ビット6~4 = シェアリングモードの設定 000 = 互換モード 001 = 読み込み/書き込みの両方の禁止 010 = 書き込み禁止 011 = 読み込み禁止 100 = 許可 ビット1~0 = 読み書きの指定 00 = 読み込みモードでオープン 01 = 書き込み〃 10 = 読み込み/書き込みのモードでオープン リターン値は、オープンしたファイルのファイルハンドルかエラーコード 8.3.2 ファイルのロックの使用方法 ファイルのロックは、DOS コールの lock($ff8c)を使用します。 lock(MD,FILENO,OFFSET,LEN) MD :1 = ファイルのロック 0 = 〃 解除 FILENO :ロックするファイルのファイルハンドル OFFSET :ロックする部分の先頭からのオフセット LEN ;ロックするバイト数 ============================================================================== 8.4 オーバーレイXファイルとバインド Human68k ver.2.0 は、「オーバーレイXファイル」という実行可能ファイルをサポ ートしています。 オーバーレイXファイルとは、複数のX形式実行可能ファイルを一つのファイルにま とめたものです。 Human68k ver.2.0 は、このオーバーレイXファイル中にある任意のX形式の実行フ ァイルをメモリにロード・実行することが出来ます。 オーバーレイXファイルは、使用可能なメモリ容量に対してプログラムやデータのサ イズが大きい場合に使用します。 メモリ不足で実行できないほど大きいプログラムを何とかして実行する一つの手段と して、プログラムを分割するという事が考えられます。 例えば、プログラムを一つのメインプログラムと複数のサブプログラムに分割してデ ィスクに格納しておき、実行する際には、メモリ上には必要なプログラムだけをその都 度ロードして実行する、という方法があります。 しかしこの場合メインプログラムがサブプログラムのロード・実行・終了の制御や、 サブプログラム同士のデータの受け渡しなどの処理を行わなければならず、プログラミ ングが難しくなります。 オーバーレイXファイルと次に解説する BIND というコマンドは、このように分割さ れたプログラムの実行を支援するものです。 8.4.1 オーバーレイXファイルの作成 オーバーレイXファイルを作るには、BIND というコマンドを使います。 BIND の書式は以下の通りです。 BIND [/O] <オーバーレイXファイル名> <ファイル名> [<ファイル名> …] [/D|/X|/L] [/T<パス名>] '['と']'で囲まれたものは省略が可能です。 また'{'で区切られているものは、そのうちの一つを選択できます。 /O スイッチは、新たにオーバーレイXファイルを作成する時に用います。例えば、 BIND /O sample.x sample1.x sample2.x sample3.x とすると、sample1.x sample2.x sample3.x を一つにまとめたオーバーレイXファイル sample.x が作成されます。 既に存在しているオーバーレイXファイルに、X形式の実行可能ファイルを追加する 場合には、以下のように実行します。 BIND sample.x sample4.x sample5.x その他のスイッチには、以下の機能があります。 ・/D スイッチ:オーバーレイXファイルの中から、指定されたファイルを削除する ・/L スイッチ:オーバーレイXファイルに含まれているファイル名を表示する ・/X スイッチ:オーバーレイXファイルの中から、指定されたファイルを取り出す ・/T スイッチ:指定されたパスに、テンポラリファイルを作成する 8.4.2 オーバーレイXファイルに含まれているプログラムの実行 オーバーレイXファイルに含まれている各ファイルには、モジュール番号が付けられ ます。オーバーレイXファイル中のファイルを選択するには、このモジュール番号を指 定します。モジュール番号は、オーバーレイXファイルに追加された順に0番から付け られます。 前述した BOND コマンドの例では、 sample1.x のモジュール番号は 0 sample2.x 〃 1 sample3.x 〃 2 sample4.x 〃 3 sample5.x 〃 4 となります。 コマンドプロセッサ(command.x)からオーバーレイXファイル"sample.x"を実行した 場合、最初にロード・実行されるのはモジュール番号0の"sample1.x"です。 なお、通常のX形式の実行可能ファイルはモジュール番号が0となっているので、そ のままロード・実行されます。 さて、"sample2.x"や"sample3.x"などモジュール番号が0以外のファイルは直接コマ ンドプロセッサから実行できません。つまり、モジュール番号が0のファイルがメイン プログラムとして動作し、モジュール番号が0以外のファイルがサブプログラムとして 必要な時だけ、メインプログラムから呼び出されるわけです。 したがって、モジュール番号が0である"sample1.x"がメインプログラムとして機能し、 "sample2.x"や"sample3.x"などのサブプログラムをロード・実行しなければなりません。 その為の DOS コールが exec($ff4b)です(本マニュアルの DOS コールの解説の exec の項を参照して下さい)。この exec のパラメータである MD にモジュール番号を指定 します。 MD の意味は以下の通りです。 15~8ビット:モジュール番号(0~255) 7~0ビット:コントロールコード 0:ロードおよび実行 1:ロードのみ 2:コマンドパスの検索 3:特殊なロード 4:実行のみ 5:モジュール番号を得る したがって、"sample1.x"から"sample2.x"をロード・実行するには、MD = $0100 と して exec($ff4b)を呼び出します。 また、ファイル名からモジュール番号を得ることが出来るので、"sample1.x"は "sample2.x"や"sample3.x"などのサブプログラムのモジュール番号を知らなくてもそれ らのプログラムを実行することが出来ます。 ============================================================================== 8.5 サンプルプログラムの解説 ここでは、サンプルプログラム hide.x を使って、バックグラウンド処理を使用した プログラムの作成方法を解説します。 このプログラムは Human68k ver.2.0 で新たに付け加えられた、次の機能を使用して います。 ・ファイルシェアリング ファイルの排他制御 ・コモンエリア プロセス、スレッド間の共有記憶領域 ・バックグラウンド処理 マルチタスクに近い並列処理 ・バインド オーバーレイXファイルの作成 8.5.1 機能と動作環境 ・"hide.x"の機能 書式)設定:hide [ファイル名] 解除:hide [パスワード] ファイル名を入力すると、パスワードと時間を聞いてきますので指示に従って入力し て下さい。 解除するには、設定時に指定したパスワードを入力して下さい。 機能) 指定した時間までファイルをロックします。 ロックとはファイルへのアクセスが禁止されることで、ファイルがオープン出来 なくなります。 リセットするとロックは解除されます。 ・"hide.x"の作成方法 リスト1が、"hide.x"を作成する為のメイクファイル"makefile"です。 実行する時には以下のことを確認して下さい。 ・カレントディレクトリに hidem.s,hidesp.s が存在する ・アセンブラ(AS.X)やリンカ(LK.X)のバージョンが2.00以降である ソースファイル"hidem.s","hidesp.s"はアセンブル・リンクされ、実行可能ファイル "hidem.x","hidesp.x"が作成されます。 "hide.x"は"hidem.x","hidesp.x"をバインドしたファイルです。 実行する時にはオーバーレイ"hide.x"を実行します。 ・システム環境の設定 このプログラムを実行するには、"CONFIG.SYS"において次のような設定をしておく必要 があります。 (1)ファイルの共有と排他制御の指定 SHARE = <ファイル数> <ロック領域数> [例] SHARE = 10 4 排他制御(ロック)を行うファイル数と、ロックする領域数を指定します。 これを設定しないと、ファイルのロックが出来ません。 (2)DOS コール common($ff85)で使用するメモリ容量の指定 COMMON = <容量> [例] COMMON = 32K DOS コールの common($ff85)で使用するメモリ容量を指定します。 common($ff85)はプロセスやスレッド間で共有するコモン領域を使用するための DOS コ ールです。 これを設定しないと、common($ff85)は使用できず、呼び出すとエラーになります。 (3)並列処理の為の制御情報の設定 PROCESS = <プログラム数> <レベル> <タイムスライス値> [例] PROCESS = 10 2 10 <プログラム数>には、並列に実行するプログラム数を2~32の範囲で指定します。 <レベル>には、プログラムの実行間隔を決める値を2~255の範囲で指定します。 値が小さいほど実行間隔が短くなるので、実行速度が速くなります。 また、<タイムスライス値>には、各プログラムの実行時間を1~100msの範囲で指定します。 PROCESS の指定がないと、並列処理は出来ません。 ・ファイルシェアリング(リスト3 134~143行) シェアリングは、ファイルの共有化に伴って、最初にファイルをオープンしたユーザが 他のユーザからのファイルのアクセスを制御するための機能です。 具体的には、DOS コールの open($ff3d)のオープンモードが拡張され、重複するファイ ルの読み書きの禁止、許可を制御することが可能になっています。 このプログラムでは、シェアリングモード $1? を使って、重複するアクセスを排除す る例を示しています。 ・コモンエリア(リスト3 91~99行、197~202行) コモンエリアは Human68k のシステムエリア内に確保され、プロセスあるいはスレッド が共有する記憶領域となります。 例えて言うなら、プロセス、スレッドの伝言板と言えます。 プロセス、スレッドからコモン領域へのアクセスは DOS コールの common($ff85)によ り行うことが出来ます。 このプログラムでは、コモネリアにファイルハンドル、パスワードを書き込んでいます。 ・バックグラウンド処理 バックグラウンド処理は、見かけ上複数のプログラムを並列に実行させるマルチタスク に近い機能を持っています。 しかし、スレッドが同時にシステムを利用できないなどの制約があります。 実際にバックグラウンドプログラムを作成する上での注意点として次の二点が上げられ ます。 (1)スレッド数と同じ数のプログラム(プロセス)を作る必要がある。 一個のプログラムでもバックグラウンド処理を行うことは可能ですが、スレッドが切り 替わると環境(プロセス管理領域に設定されている CTRL-C や OS のエラーアボートの 処理先など)も切り替わるようにすべきです。 そうしないと、各スレッドが環境を共有することになり、あるスレッドが環境の変更な どを行なうと他のスレッドにも影響してしまうからです。 しかし、同一プロセス内では、それらのプロセス管理情報は Human68k では1プロセス に一つしか持つことが出来ません。 したがって、実際にそれらを各スレッド毎に切り替える為には、各スレッドを別の子プ ロセスとして実行し、スレッドの最初で環境を変更する必要があります。 (2)バックグラウンド処理を行うプログラムは常駐プログラムにする必要があります。 通常のプログラムは、プログラムが終了するとメモリから削除されます。 ところが、常駐プログラムは、プログラムが終了してもその一部をメモリ上に残し、後 から何らかの方法で呼び出され、処理を行います。 バックグラウンドプログラムは、親プロセスと子プロセスの二個のプログラムからなり、 子プロセスは常駐プログラムになります。 サンプルプログラムでは親プロセスが"hidem.s"、子プロセスが"hidesp.s"に相当します。 8.5.2 親プロセス(リスト2:hidem.s) 親プロセスでは二つの働きを行います。 ・スレッドが無ければ、子プロセスを実行してスレッドを生成する。 ・スレッドが有れば、スレッド間通信で破棄要求を行う。 親プロセスは次のような構成となります。 (1)DOS のバージョンを調べる(85~92行) 実行可能な DOS のバージョンは2.00~2.49です。 DOS コールの vernum($ff30)を用います。 (2)スレッドの有無を調べる(119~131行) スレッドが既に存在していたら(7)で分岐、存在していなければ(3)へ進みます。 ここでは DOS コールの get_pr($fffa)を用います。 (3)子プロセスを実行する(17,21~31行) ここでは DOS コールの exec($ff4b)を用います。 サンプルではオーバーレイファイル中のプロセスを実行しています。 子プロセスは、バックグラウンド処理部をスリープ状態でメモリに常駐させます。 (4)スレッドは永久スリープ状態なのでスレッドをアクティブにするコマンド($fffb)を 通信する(62~67,104~118行) ここでは DOS コールの send_pr($fffd)を用いて通信を行います。 (5)終了する(20行) (6)通信パラメータとして自分とスレッドの ID 番号を求める(119~131行) ここでは DOS コールの get_pr($fffa)を用います。 (7)スレッドにスレッドの破棄要求($fff9)を通信する(65~77行) ここでは、send_pr($fffd)を用いて通信を行います。 ただし、サンプルプログラムでは、スレッドに破棄要求は行わず、自己破棄を行わせます。 (8)終了する(19~20行) 8.5.3 子プロセス(リスト3:hidesp.s) 子プロセスは大きく二つに分かれています。バックグラウンド処理を行う常駐部と、 スレッドの生成及び常駐終了を行う非常駐部です。 バックグラウンド処理部分は前に、スレッドの生成、常駐終了部分は後ろに配置され ます。そして、後ろの部分は親プロセスから子プロセスとして実行され、常駐終了時に 切り捨てられます。 常駐部は次の働きを行います。 ・環境の設定 ・スレッド間通信の受信 ・スレッドの破棄 ・バックグラウンド処理 非常駐部は次の働きを行います。 ・スレッドの新規生成 ・バックグラウンド処理部のメモリ常駐 常駐部分は次のような構成になります。 (1)環境の設定(14~15,39~49行) スレッドの切り替わりとともに、CTRL-C や エラーアボートの処理先を変更します。 ここでは DOS コールの intvcs($ff25)を用います。 (2)スレッド間通信の受信(16~38行) 他のスレッドから通信が来ると通信バッファに必要な情報が格納されます。またスリ ープ状態だった場合はアクティブ状態にされます。 スレッド間通信バッファからコマンド、データを読み取り、それに対応した処理プロ グラムに分岐します。 通信バッファの内容については DOS コールの open_pr($fff8)、通信バッファからの 読み出しの手順については sleep_pr($fffc)の解説を参照して下さい。 この部分の最後で、DOS コールの sleep_pr($fffc)によってスレッドをスリープ状態 にしています。これは、スレッドの処理を軽減し、割り当てられた時間を全て使わずに、 システム全体の処理速度遅くさせないためです。次の処理が要求されるまで、処理する ものがなければ、必ずスリープ状態になるようにして下さい。 (3)スレッドの破棄(03行) ここでは、DOS コールの kill_pr($fff9)を用います。 スレッド間通信で破棄要求コマンド($fff9)を受信した時、スレッドはそれが受け入 れられる要求であれば、要求にしたがって破棄します。受け入れられない要求であれば、 その要求を捨てた後、実行権を破棄します。 その後、要求を発行したスレッドに実行権が戻ってきた時点で、要求したスレッドの 詳細情報の取得を DOS コールの get_pr($fffa)で試みます。取得が成功すれば、破棄 できなかったことを示します。失敗すれば、破棄できたことを示します。 自分自信のスレッドを破棄したい場合は、まず、永久スリープ状態に入り、他のスレ ッドからアクティブ状態にされるまで待機します。他のスレッドは、どれかのスレッド が上記のような待機状態になっている可能性があるので、定期的に通信を行います。そ してこの時、通信に失敗したならば、そのスレッドが自分自信の破棄を行ったことを知 ります。 スレッドを破棄する場合、スレッドを無秩序に破棄してはいけません。無秩序に破棄 を行うと、システムで回復不可能な致命的な異常が発生する場合があります。 (4)バックグラウンド処理本体(53~101行) ここでは、ユーザが任意のプログラムを作成できます。 ただし、制約がありますので、後述の注意事項を参照して下さい。 以上がバックグラウンド処理本体となってメモリに常駐します。 次に、非常駐部を説明します。 (5)スレッドの新規生成(203~216行) ここでは、DOS コールの open_pr($fff8)を用います。 (6)常駐終了(217~221行) ここでは、DOS コールの keeppr($ff31)を用います。 バックグラウンド処理のデータ、ワーク、スタックエリアを置く位置によって、常駐 するプログラム範囲が違います。 つまり、子プロセスの最後にそれらを置くと、プログラム全部を常駐しなければなり ません。しかし、本来この部分は非常駐部分なので、このプログラムのようにデータ、 ワーク、スタックエリアをこのすぐ上、つまり、バックグラウンド処理の最後におきま す。そうすると、常駐範囲はそこまでで良いので、常駐サイズは小さくなります。 この時、注意することはデータ、スタックなどもテキストセクション(.text)に置か なければならないことです。したがって、.data、.bss、.stack などのセクション擬似 命令をそこには記述しないように注意して下さい。 親プロセス 子プロセス ┌───────────────┐┌──────────────┐ │ ││─ 常駐部 ─ │ │ ││ │ │ ││メモリに常駐しバックグラウン│ │1.スレッドがない時は、子プロセ││ド処理を行う │ │ スの非常駐部を実行し、永久ス││ │ │ リープ状態の常駐部をアクティ││データをここに書く時は .data│ │ ブにするように通信する ││.bss、.stack を入れない │ │ ││ │ │ │├──────────────┤ │2.スレッドがある時は、常駐部に││─ 非常駐部 ─ │ │ 破棄要求を通信する ││常駐部をスレッドとして生成し│ │ ││常駐終了させる │ │ ││ │ │ ││この部分はメモリには残らない│ └───────────────┘└──────────────┘ 8.5.4 プログラム作成上の注意事項 ・子プロセスでプログラムの途中を実行アドレスにする場合、.end 擬似命令の後ろに ラベルを書くと、そのラベルから実行が開始されます。 ・バックグラウンド処理は、デバッガ(DB.X)でトレースすることが出来ません。 不完全なプログラムをスレッドとして動かすと、止めることが困難でシステムを破壊 する恐れさえあります。 したがって開発にあたっては、常駐部と非常駐部に分けてそれぞれが完全に動作する まで十分にデバッグして下さい。 ・前述のように、バックグラウンドには複数のプログラムが必要です。そこで、BIND コマンドを用いて一個のプログラムにまとめます。 BIND コマンドを使う利点として次のことがあります。 (1)一個のファイルとして扱えるので取り扱いが便利 (2)子プロセスのファイル名を変更される恐れがない (3)子プロセスを実行する時、自分のバインドファイル名を使っているので、ファイル 名を変更しても関係なく実行できる (4)DOS のバージョンなどの初期環境を調べるルーチン最初のプログラムだけですむ バックグラウンド処理プログラムを作成する場合は必ず、BIND コマンドで一個のフ ァイルにして下さい。 8.5.5 サンプルプログラム・リスト 省略 ==============================================================================