*シグナルの使い方
#contents
**本文
SSS-PCのシステムコールを直につかったサンプルを書こうと思ったのですが、
UNIX互換libcを使っているなら、通常のsignal()等の関数を
お使いになられるのが便利です。
この場合は、SIGUSR1かSIGUSR2を使うことになりますが、
これらが他の用途で埋まっていると元のコードを少し変更する
必要があります。
互換ライブラリを使っていない場合は、
以下のような感じでsiganlの関数を登録してください。
void
signal_dispatch(interrupt,sw_f)
int interrupt;
int sw_f;
{
int pattern;
printf("interrupt=0x%x\n",interrupt);
if (interrupt & TASK_SIGALRM) {
printf("SIGALRM catched!!\n");
/* SIGALRM 処理 */
}
if (interrupt & TASK_SIGLIBC) {
printf("SIGLIBC catched!!\n");
pattern = self_getparam(TASK_GETPARAM_SIGLIBC_VALUE_CLR);
/* SIGLIBC 処理 */
}
clear_signal_blkmask(0xffffffff);
return;
}
main()
{
set_signal_func(signal_dispatch);
set_signal_event(0xffffffff);
clear_signal_blkmask(0xffffffff);
for(;;)
self_sleep(100);
}
発生したsignalはsignal_dispatch()の第一引数である
interruptのビットパタンで表します。
例えば、
SIGHUP: 1 (TASK_SIGHUP)
SIGALRM: 0x2000 (TASK_SIGALRM)
です。
複数の要因が同時にセットされる場合もあります。
signal_blkmaskはsigmaskに相当して、
clear_signal_blkmask(0xffffffff);
はすべてのシグナル要因で割り込みを受け付けることを意味します。
set_signal_blkmask(0xffffffff);
なら、すべてのシグナル要因をブロックすることを意味します。
set_signal_event(0xffffffff);
はUNIXにはない仕様ですが、使用するsignal要因をセットします。
ここで1がセットされていないsignal要因は使用されません
(ブロックではないのでシグナルが発生したことも忘れます)。
シグナルを発生させるには、
send_task_signal(taskID,sig_pattern);
を使うか、nikomonコマンドで
:-) signal -send <taskID> <sig_pattern>
と打ってください。
ただし、現在農工大に出荷しているバージョンでは、
同じnikomonシェルから起動されていないタスク間には
このUNIXライクsignalは飛ばせない仕様になってます。
最新版では権限がrootであれば、違うnikomonシェルを
親に持っていても、飛ばせることになっています。
set_signal_func()でユーザがsignal処理関数を登録してしまうと、
UNIX互換ライブラリが設定したsignal処理関数が無効になって
しまうため、signalに関するUNIX互換性はなくなります。
TASK_SIGLIBC 0x80000000 /* special signal for u-libc, siglibc_value */
というのが拡張としてもうけられていて、
interruptのビットパタンが0x80000000 だった場合には、
pattern = self_getparam(TASK_GETPARAM_SIGLIBC_VALUE_CLR);
でもう一つintのベクタを取り出すことができます。
SIGLIBCのsignalは
send_libc_signal(task,sig_pattern)
か
:-) signal -sendlibc <taskID> <sig_pattern>
で発生させられます。
UNIXライクsignalにはもう一つ拡張があって、
それが前回のメールに添付したsgid=1に相当する
signalです。
こちらはUNIX互換libcではまだ使っていないので、
UNIX互換libcと両立できる可能性があります。
set_signal_event_ex(pattern,sgid) /* 1が立ったbitに相当するsignalが使用可能になる */
set_signal_blkmask_ex(pattern,sgid) /* 1が立ったbitに相当するsignalがblockされる */
void(*set_signal_func_ex(func,sgid))()
clear_signal_blkmask_ex(pattern,sgid) /* 1が立ったbitに相当するsignalがunblockされる */
send_task_signal_ex(task,sig_pattern,sgid)
で使用できます。
sgid=0の場合は最初に説明したUNIXライクsignalと同じ物です。
sgid=1のケースも割り込み要因はシステムでほとんど埋まっていて、
ビット30,ビット31ぐらいを使っていただけるとありがたいです。
ssscore.hにSIGTASKQ0とかいった定数ででているものが割り込み要因で、
主にMBCF関係のユーザプログラムの非同期呼び出しに使います。
ユーザプログラム内で明示的に使用するように設定しなければ
これらの割り込み要因は発生しませんが、トラブルを避けるためには
なるべく用途が決まったビットは使用しない方がよいでしょう。
**システムコール解説
***set_signal_func
void (*set_signal_func(func))()
void (*func)();
UNIXタイプsignalのユーザ定義割り込み関数をセットする。
ただし、1タスクに1関数しか定義できない。
funcの第一引数に割り込み要因を示すビットベクタが渡される。
***set_signal_event
int set_signal_event(pattern)
int pattern;
1が立ったbitに相当するUNIXタイプsignalが使用可能になる
設定変更後のsignal_condの値が返る
なお、UNIXタイプsignalは基本的にUNIXとの互換性を取るために実装
されたものであり、SSS-PCカーネルは現在以下のイベントしか
発生させない。
TASK_SIGILL : SIGILL相当 illegal instruction (not reset when caught)
TASK_SIGFPE : SIGFPE相当 floating point exception
TASK_SIGALRM : SIGALRM相当 alarm clock
TASK_SIGURG : SIGURG相当 urgent condition on IO channel
TASK_SIGCHLD : SIGCHLD相当 to parent on child stop or exit
TASK_SIGWINCH : SIGWINCH相当 window changed (via telnet connection)
TASK_SIGMiG : SSS-PCオリジナル recommendation to escape from the current node
他のイベントはユーザアプリケーションが
send_task_signal()を使って、またはシェルからsignalコマンド
を使って明示的に発生させられる。
***clear_signal_blkmask
int set_signal_blkmask(pattern)
int pattern;
1が立ったbitに相当するsignalがunblockされる。
unblockされたイベントがすでに発生していた場合には割り込み関数が
呼び出される。
unblockで起動されたsignalのビットベクタが返る
注意:設定変更後のsignal_blkmaskの補数(1がマスクされたsignal)は返らない
**シグナル
/* UNIX-type signal bit-vectors */
#define TASK_SIGHUP 1 /* hangup */
#define TASK_SIGINT 2 /* interrupt */
#define TASK_SIGQUIT 4 /* quit */
#define TASK_SIGILL 8 /* illegal instruction (not reset when caught) */
#define TASK_SIGTRAP 0x10 /* trace trap (not reset when caught) */
#define TASK_SIGABRT 0x20 /* used by abort, replace SIGIOT in the future */
#define TASK_SIGEMT 0x40 /* EMT instruction */
#define TASK_SIGFPE 0x80 /* floating point exception */
#define TASK_SIGKILL 0x100 /* kill (cannot be caught or ignored) */
#define TASK_SIGBUS 0x200 /* bus error */
#define TASK_SIGSEGV 0x400 /* segmentation violation */
#define TASK_SIGSYS 0x800 /* bad argument to system call */
#define TASK_SIGPIPE 0x1000 /* write on a pipe with no one to read it */
#define TASK_SIGALRM 0x2000 /* alarm clock */
#define TASK_SIGTERM 0x4000 /* software termination signal from kill */
#define TASK_SIGURG 0x8000 /* urgent condition on IO channel */
#define TASK_SIGSTOP 0x10000 /* sendable stop signal not from tty */
#define TASK_SIGTSTP 0x20000 /* stop signal from tty */
#define TASK_SIGCONT 0x40000 /* continue a stopped process */
#define TASK_SIGCHLD 0x80000 /* to parent on child stop or exit */
#define TASK_SIGCLD 0x80000 /* System V name for SIGCHLD */
#define TASK_SIGTTIN 0x100000 /* to readers pgrp upon background tty read */
#define TASK_SIGTTOU 0x200000 /* like TTIN for output if (tp->t_local<OSTOP) */
#define TASK_SIGIO 0x400000 /* input/output possible signal */
#define TASK_SIGPOLL TASK_SIGIO /* System V name for SIGIO */
#define TASK_SIGXCPU 0x800000 /* exceeded CPU time limit */
#define TASK_SIGXFSZ 0x1000000 /* exceeded file size limit */
#define TASK_SIGVTALRM 0x2000000 /* virtual time alarm */
#define TASK_SIGPROF 0x4000000 /* profiling time alarm */
#define TASK_SIGWINCH 0x8000000 /* window changed */
#define TASK_SIGLOST 0x10000000 /* resource lost (eg, record-lock lost) */
#define TASK_SIGUSR1 0x20000000 /* user defined signal 1 */
#define TASK_SIGUSR2 0x40000000 /* user defined signal 2 */
#define TASK_SIGLIBC 0x80000000 /* special signal for u-libc, siglibc_value */
#define TASK_SIGMiG 0x80000000 /* recommendation to escape from the current node */
**参考情報
> Subject: [Fwd: Re: ちょっと質問です]
> Date: Mon, 26 Sep 2005 17:58:28 +0900
[[Lab/SSS-PC]]