
ダウンロードNOW!(全ソース & サンプルプログラム & 実行環境)
【GEN16最低マシンスペック】
機種 IBM PC/AT互換機 または NEC PC-9801 シリーズ
CPU Intel i386以上
メモリ 基本640KBあればOK
OS MS-DOS Ver 3.x 以上
【開発環境】
MASM Version5.0
MS−C Version6.0
【プログラム作成時の注意事項】
コンパイラのスイッチには、必ず以下の設定をしてください。この設定をしない・リンク時の注意事項
場合、アプリケーションが正常に動作しない可能性があります。
コンパイルスイッチ: /ALu
コンパイル例 : cl /ALu /c file_name.c
Generic16システムの各プロセスは、各EXEファイルに予め割り当てられた
スタック領域を分けあって使用します(実際はalloca関数を使って各プロセスのスタックを
割り当てています)。そのため、リンク時には大きめのスタック領域を設定する
必要があります。
リンクオプション: /stack:20000
リンク例 : link /stack:20000 filename,,,genclib.lib;
【Generic16カーネルの技術的資料】
・Generic16カーネルは以下の割り込みベクタを使用します。
リクエスト受付ベクタ F0h
タイマー割り込みベクタ 1Ch
・Generic16カーネルの各種サービスに於ける最大値を示します。
最大プロセス数 = 32・Generic16カーネルが参照しているMS−DOSファンクションについて
IPC_POSTで一度にバインドできるプロセス数 = 32
IPC_POSTでCreateできるキーの最大数 = 32
Exportできるアドレスの最大数 = 255
タイマーエレメント最大数 = 32
セマフォ最大数 = 32
Generic16カーネルは、未公開のものも含めて幾つかのMS−DOS
ファンクションを使用していますが、以下に特に重要と思われる情報について
記述します。
PSPの再設定として ah=50h, INT 21h
ディスク転送アドレスの再設定として ah=1ah, INT 21h
PSPの取得として ah=51h, INT 21h
ディスク転送アドレスの取得として ah=2fh, INT 21h
IN-DOSフラグ・致命的エラーアドレスぜ萋 ah=34h, INT 21h
【GEN16 APIリファレンス】
シンボル 名 称 _checkstay カーネル常駐有無判定 CreateThread プロセス登録 dispatch 1サイクルSleep getpid 自プロセスid取得処理 kernel_start カーネル制御開始 kernel_quit カーネル制御終了 getstate プロセス状態取得 setstate プロセス状態設定 kill プロセス削除 export アドレスエクスポート import アドレスインポート unexport エクスポートされたアドレスの破棄 ipc_pinit ポスト初期化 ipc_post ポスト通知 ipc_precv ポスト受信 TimerSet タイマー設定 TimerGet タイマー設定値取得 ipc_semget セマフォ取得 ipc_semop セマフォ操作 kbd_scan キー入力待ち kbd_input キー入力 sleep プロセススリープ modeget カーネル動作モード取得 TimeSlice 時分割平行処理開始・停止 getpinfo プロセス情報取得
Title : _checkstay (カーネル常駐有無判定)
int _checkstay( void )Title : CreateThread (プロセス登録)
Generic−16カーネルが常駐していれば 0 を返します。
常駐していない場合は -1 を返します。
int CreateThread(char *func,char *stack,int stacklen)Title : dispatch (1サイクルSleep)
( IN) func = プロセス(関数)のアドレス
( IN) stack = プロセスに割り当てるスタックのアドレス
( IN) stacklen = プロセスに割り当てるスタックのサイズ
処理成功時は、-1以外の値(プロセスID)を返します。
処理失敗時は、-1を返します。
void dispatch( void )Title : getpid (自プロセスid取得処理)
この処理を呼び出したプロセスは、レディー状態のまま実行権を他の
プロセスに譲ります。無限ループなどでシステムのパフォーマンスが落ちる
場合などに定期的に他プロセスを起動するために使用します。
int getpid( void )Title : kernel_start (カーネル制御開始)
自プロセスのpidを返します。この関数を、割り込みルーチン内などで
使用した場合は、現在実行中のプロセスのidが返ります。
処理成功時は、-1以外の値(プロセスID)を返します。
処理失敗時は、-1を返します。
void kernel_start( void )Title : kernel_quit (カーネル制御終了)
Generic−16のプロセスモニタリング処理が開始されます。
この関数を実行した直後は、タイムスライス(時分割平行処理)が
行われない設定になっています。タイムスライスによるマルチタスク処理を
開始したい場合は、 TimeSlice()関数によってタイムスライス開始要求を
発行してください。
Void kernel_quit( void )Title : getstate (プロセス状態取得)
カーネルの処理を中止し、kernel_start()関数を発行した直後の行へ
処理を返します。
int getstate( int pid )Title : setstate (プロセス状態設定)
( IN) pid = 対象となるプロセスのid
pidで指定されたプロセスの状態を返します。状態が0の場合は、
そのプロセスは実行可能状態です。0以外の場合は、何等かの要因で
待ち状態に入っています。
処理成功時は、-1以外の値(プロセス状態)を返します。
処理失敗時は、-1を返します。
int setstate(int pid, int state)Title : kill (プロセス削除)
( IN) pid = 対象となるプロセスのid
( IN) state = プロセス状態
getstate()関数で取得した状態を変更します。ただし stateの下位8ビット
はシステムで予約していますので、絶対に変更しないでください。上位8
ビットはユーザーに開放されていますので、自由に設定できます。プロセス
状態が0以外になっているプロセスは、スケジューリングから除外されます。
処理成功時は、-1以外の値を返します。処理失敗時は、-1を返します。
int kill( int pid )Title : export (アドレスエクスポート)
( IN) pid = 対象となるプロセスのid
pidで指定したプロセスが消去されます。自プロセスに対してkill()関数を
使用した場合、自プロセスの情報削除後、即座に他プロセスへ実行権が移り
ますので、kill()関数より後の行は実行されません。また、ポストを取得し
ている場合は、自動的に開放されます。
処理成功時は、-1以外の値を返します。処理失敗時は、-1を返します。
int export(int key, char *addr)Title : import (アドレスインポート)
( IN) key = キー値
( IN) addr = エクスポートするアドレス
EXEファイル間でデータの交換がしたい場合や関数を相互に呼び出したい
場合に使用します。addrで指定するアドレスには、スタック領域のアドレス
を指定しないほうが良いでしょう。処理成功時は、-1以外の値を返します。
処理失敗時は、-1を返します。
char *import(int key)Title : unexport (エクスポートされたアドレスの破棄)
( IN) key = キー値
export()関数で指定したキー値と一致するキー値を指定すると、そのキーに
対応するアドレス値が返却されます。処理成功時は、NULL以外の値を返しま
す。処理失敗時は、NULLを返します。
int unexport(int key)Title : ipc_pinit (ポスト初期化)
( IN) key = キー値
キー値で指定されたエクスポート情報を破棄します。
処理成功時は、-1以外の値を返します。処理失敗時は、-1を返します。
int ipc_pinit(int key)Title : ipc_post (ポスト通知)
( IN) key = キー値
キー値に対応するポスト領域を取得します。初めて使用されるキー値の
場合、ポストバッファの初期化が行われます。既に他のプロセスで初期化
されているポストバッファに対して ipc_pinit()関数を実行すると、既存の
ポストバッファに自プロセスのidをバインドします。処理成功時は、
-1以外の値を返します。処理失敗時は、-1を返します。
int ipc_post(int key, int mesg)Title : ipc_precv (ポスト受信)
( IN) key = キー値
( IN) mesg = 送信メッセージ
キー値に対応するポストバッファにメッセージを書き込みます。この時、
ipc_pinit()関数を使用してバインドしたすべてのプロセスにメッセージが
届きます。処理成功時は、-1以外の値を返します。処理失敗時は、-1を
返します。
int ipc_precv(int key, int mask, int ntype)Title : TimerSet (タイマー設定)
( IN) key = キー値
( IN) mask = 受信マスク
( IN) ntype= 受信動作指定
キー値に対応するポストバッファからメッセージを受信します。未だ
メッセージが届いていない状態でこの関数を実行すると、プロセスが待ち
状態になり、メッセージが送信されるまで待機します。受信マスクは、
ポストされるメッセージを限定する際に使用します。例えば、送信側が
メッセージ(0x01)を送信し、受信側では受信マスクとして
(0x02)を指定していた場合、受信側にはメッセージが届きません。
送信側が0x03や0xFF等のように0x02のビットを含んだ
メッセージを送信した場合、受信側には0x02のみが返却されます。
残ったビットは保留され、次に受信側が残りのビットを受信しようとする
まで残ります。処理成功時は、受信したメッセージの値を返します。
処理失敗時は、-1を返します。
受信動作指定(ntype)には、以下の値を設定できます。
PRECV_NOWAIT = 受信メッセージが無い場合エラー復帰
PRECV_WAIT = 受信メッセージが届くまで待つ
int TimerSet(int elem,int tick,int post_key,int post_code)Title : TimerGet (タイマー設定値取得)
( IN) elem = タイマーエレメント番号
( IN) tick = タイマー間隔(1=50msec)
( IN) post_key = タイムアウト通知ポストキー
( IN) post_code = タイムアウト通知コード
elemで指定したタイマー(0〜31)を設定します。tickは50msec
単位で何回カウントする毎にメッセージをポストするかを指定します。
タイムアウト自には、post_keyで示されるポストキーにpost_codeで指定
されたメッセージが送信されます。処理成功時は、-1以外の値を返します。
処理失敗時は、-1を返します。
int TimerGet(int elem, struct _tmgetinf far *pbuf)Title : ipc_semget (セマフォ取得)
( IN) elem = タイマーエレメント番号
(OUT) pbuf = タイマー情報構造体
elemで指定したタイマー(0〜31)の設定状態を返します。
タイマー構造体のメンバーは以下の通り。
struct _tmgetinf {
int nkyT ; /* 受信者 IPC_POSTキー */} ;
int nCdT ; /* 受信者 IPC_POSTコード */
int norg ; /* タイムアウト叩癖歛戸僉 */
int ncur ; /* カレントタイマー値 */
int ipc_semget(int key, int max)Title : ipc_semop (セマフォ操作)
( IN) key = セマフォキー値
( IN) max = セマフォ最大値
セマフォを作成する。
処理成功時は、-1以外の値を返します。処理失敗時は、-1を返します。
int ipc_semop(int key, int cmd)Title : kbd_scan (キー入力待ち)
( IN) key = セマフォキー値
( IN) cmd = セマフォ操作命令
キー値で指定されたセマフォに、セマフォ操作命令で指定された操作を
行います。操作命令として指定できるのは以下の通り。
SEM_LOCK セマフォ増加
SEM_UNLOCK セマフォ減少
SEM_NWLOCK 待ち無しでセマフォ増加
SEM_LOAD セマフォ状態取得
1) SEM_LOCK / SEM_NWLOCK
セマフォを増加します。ipc_semget()関数で指定した maxサイズに
なるまで増加できますが、maxを越えて増加しようとした場合、
SEM_LOCKでは他プロセスがセマフォを減少させるまで待ち状態に
入り、SEM_NWLOCKでは、エラー(-1)復帰します。
2) SEM_UNLOCK
セマフォを減少させます。セマフォは0以下の値に成る事はありません。
3) SEM_LOAD
セマフォの現在の値を返します。
int kbd_scan( void )Title : kbd_input (キー入力)
キーボードの入力が有る場合1を返します。キー入力が無い場合0を
返します。
int kbd_input( void )Title : sleep (プロセススリープ)
キーボードから文字を1文字入力します。何もキーボードを押していない
時に本関数を呼び出すと、待ち状態になりますが、他プロセスへは制御を
渡さないので、注意してください。
void sleep( int cnt )Title : modeget (カーネル動作モード取得)
( IN) cnt = ディスパッチ回数
cntで指定された回数分他プロセスへ実行権を回します。
int modeget( struct _modgetbuf *pbuf)Title : TimeSlice (時分割平行処理開始・停止)
(OUT) pbuf = カーネル状態バッファ
カーネルの現在の動作状態を返します。
カーネル状態バッファの内容は以下の通り。
struct _modgetbuf {
int nmacid ; /* 動作機種 1=PC_9801, 2=IBM_PC */} ;
int ntmslice ; /* タイムスライス楊 */
int nkernel ; /* カーネル動作状態 0=停止,1=動作中,2=終了中*/
int nmaxtss ; /* 登録可能最大プロセス */
int nmaxpost ; /* 登録可能最大POST数 */
int nmaxexp ; /* 登録可能最大EXPORT数 */
int nmaxtimer ; /* 登録可能最大タイマー数 */
int nmaxsemafo ; /* 登録可能最大セマフォ数 */
void TimeSlice( int flag )Title : getpinfo (プロセス情報取得)
( IN) flag = タイムスライス有無フラグ
このフラグに1を指定すると、時分割平行処理がスタートします。
0を指定すると、時分割平行処理をストップします。
#define TMC_TMCLON 1 /* Time Slice Start */
#define TMC_TMCLOF 0 /* Time Slice Stop */
int getpinfo(int pid, struct _pinfo *pbuf)
pid = 対象となるプロセスのid
pbuf = プロセス情報バッファ
指定したプロセスの情報をプロセス情報バッファに書き込みます。
プロセス情報バッファの構造は以下の通り。
struct _pinfo {
int nptyp ; /* プロセスタイプ */} ;
long nstack ; /* スタックフレームアドレス */
int npid ; /* PID */
int psp ; /* PSP */
long dta ; /* DTA */