|
|
|
| 2008/10/07 11:49||▲
|
|
|
前回は、シグナル処理ルーチンの方針について書きました。今回と次回は、その方針に基づいて、実際にsignal関数とraise関数を実装することにします。
今回の関数は、初めてOSに依存したコードになります。といっても、簡単な排他制御だけですので、普通に割り込みを禁止してもよいのですが、他のターゲットへの移植性を考慮して、μITRONの機能を使うことにします。
それでは、実装を見てみましょう。
#include <signal.h> #include <errno.h>
#define SIGMAX 6 static void (*signal_handler_table[SIGMAX])(int);
void (* signal(int sig, void (*func)(int)) )(int) { if (sig < 1 || SIGMAX < sig || func == SIG_ERR) { errno = EDOM; return SIG_ERR; }
BOOL f = sns_loc(); loc_cpu(); void (*result)(int) = signal_handler_table[sig-1]; signal_handler_table[sig-1] = func; if (!f) unl_cpu();
return result; }
前半部は引数のチェックを行っています。sigで指定したシグナル番号の範囲と、念のためfuncにSIG_ERRを誤って指定していないかどうかだけのチェックにとどめています。funcに空ポインタを指定した場合、SIG_DFLとの区別が付きませんので、特に何もしていません。
エラーを検出した場合、SIG_ERRを返すとともに、errnoに正の値を設定しなければならないため、ここではEDOMを設定しています。他のエラー番号を設けてもよいのですが、今回はそこまでする必要もないと判断しました。
シグナル処理ルーチンは、signal_handler_table配列に格納されます。静的な配列ですので、その内容は空ポインタ(=SIG_DFL)で初期化されることが期待できます。また、raise関数も同じ翻訳単位に収めることにすれば、この配列は内部結合となり、外部から参照されるおそれがなくなります。
signal_handler_table配列の操作は、排他制御が必要ですので、sns_loc、loc_cpu、およびunl_cpuというサービスコールを使用しています。これらはCPUロック状態の制御を行うもので、すごく乱暴に言ってしまえば、割り込み禁止の制御を行っています。
signal関数は、非タスクコンテキストで呼ばれることを想定していません。そのため、sns_ctxでコンテキストの状態を調べてることなく、(iloc_cpuやiunl_cpuではなく)loc_cpuやunl_cpuを問答無用で呼び出しています。非タスクコンテキストに対応するするには、SIL*1を使った方が便利かと思います。
*1 ITRONデバイスドライバ設計ガイドラインの一部分として検討されているシステムインタフェースレイヤのこと。TOPPERS/JSPカーネルは、そのサブセットをサポートしています。
|
| 2006/05/16 00:07|シグナル処理|TB:0|CM:0|▲
|
|
|
コメント
|
|
コメントの投稿
|
|
|
|
|
トラックバック
|
トラックバックURLはこちら
http://libc.blog47.fc2.com/tb.php/54-45e79bf1
|
|
|
|
|
ホーム
全記事一覧
<< 前の記事
次の記事 >>
|