前へ | 次へ | 目次 | 索引 |
シグナルとは,ユーザ・プロセスの通常の実行に対するソフトウェア割り込みです。シグナルは次に示すイベントなど,さまざまなイベントの結果として発生します。
OpenVMS システムと UNIX システムはどちらも,シグナル処理機能を備えています。 2 つのシステムでこれらの機能は異なる動作をしますが,使用する用語は類似しています。 HP C RTL では,プログラミングの際にどちらのシグナル処理機能も使用できます。シグナル処理ルーチンについて説明する前に,一部の用語について定義しておく必要があります。
UNIX では,ソフトウェア割り込みのことをシグナルと呼びます。 UNIX システムでシグナルを処理するために呼び出すルーチンを シグナル・ハンドラと呼びます。
OpenVMS システムでは,ソフトウェア割り込みのことをシグナル, 条件,例外などと呼びます。 OpenVMS システムでソフトウェア割り込みを処理するために呼び出すルーチンのことをシグナル・ハンドラ, 条件ハンドラ,例外ハンドラと呼びます。
混乱を避けるために,本書では,シグナルおよび
シグナル・ハンドラという用語は, UNIX の割り込みおよび割り込み処理ルーチンのことを参照し,
例外および例外ハンドラという用語は, OpenVMS の割り込みおよび割り込み処理ルーチンのことを参照することにします。
4.2.2 UNIX のシグナルと HP C RTL
シグナルは <signal.h>ヘッダ・ファイルに定義されているニーモニックによって表現されます。 表 4-3 は,サポートされるシグナル・ニーモニックと, OpenVMS オペレーティング・システムで各シグナルを生成するイベントを示しています。
名前 | 説明 | シグナルを生成するイベント |
---|---|---|
SIGABRT 1 | 強制終了 | abort () |
SIGALRM | アラーム・クロック | タイマ AST, alarm ルーチン |
SIGBUS | バス・エラー | アクセス違反または変更モード・ユーザ |
SIGCHLD | 子プロセスの停止 | 子プロセスの終了または停止 |
SIGEMT | EMT 命令 | 互換性モード・トラップまたはカスタマに予約されている op コード |
SIGFPE | 浮動小数点例外 | 浮動小数点オーバフロー/アンダフロー |
SIGHUP | ハングアップ | データ・セット・ハングアップ |
SIGILL 1 | 不正な命令 | 不正な命令,予約オペランド,予約アドレス・モード |
SIGINT 4 | 割り込み | OpenVMS Ctrl/C 割り込み |
SIGIOT 1 | IOT 命令 | カスタマに予約されている op コード |
SIGKILL 2, 3 | 削除 | 外部シグナルのみ |
SIGQUIT 5 | 中止 | インプリメントされていない |
SIGPIPE | 破壊されたパイプ | リーダのないパイプへの書き込み |
SIGSEGV | セグメント違反 | 長さ違反または変更モード・ユーザ |
SIGSYS | システム呼び出しエラー | システム呼び出しに対する不正な引数 |
SIGTERM | ソフトウェアの終了 | 外部シグナルのみ |
SIGTRAP 1 | トレース・トラップ | TBIT トレース・トラップまたはブレークポイント・フォルト命令 |
SIGUSR1 | ユーザ定義シグナル | シグナルを送信するための明示的なプログラム呼び出し |
SIGUSR2 | ユーザ定義シグナル | シグナルを送信するための明示的なプログラム呼び出し |
SIGWINCH 6 | ウィンドウ・サイズの変更 | シグナルを送信するための明示的なプログラム呼び出し |
デフォルト設定では,シグナル (SIGCHLD を除く) が発生すると,プロセスは終了します。しかし,次のいずれかの関数を使用してシグナルを無視するように設定することができます。
sigaction
signal
sigvec
ssignal
次のいずれかの関数を使用して,シグナルをブロックすることもできます。
sigblock
sigsetmask
sigprocmask
sigsuspend
sigpause
表 4-3 は,無視またはブロックできないシグナルを示しています。
次のいずれかの関数を使用して,シグナルを検出および処理するためにシグナル・ハンドラを設定することもできます。
sigaction
signal
sigvec
ssignal
表 4-3 に示した場合を除き,各シグナルはリセットできます。シグナル・ハンドラ関数が signalまたは ssignalを呼び出して,シグナルを検出するように再設定した場合,シグナルはリセットされます。 例 4-1 は,シグナル・ハンドラの設定方法とシグナルのリセット方法を示しています。
シグナル・ハンドラの呼び出しインタフェースは次のとおりです。
void handler (int sigint); |
ただし,sigint は,このハンドラを呼び出す原因になるシグナルのシグナル番号です。
sigvecによってインストールされたシグナル・ハンドラは,変更されるまでインストールされたままになります。
signalまたは signalによってインストールされたシグナル・ハンドラは,シグナルが生成されるまでインストールされたままになります。
複数のシグナルに対して 1 つのシグナル・ハンドラをインストールすることができます。このことを制御するには, SA_RESETHAND フラグを使用して
sigactionルーチンを呼び出します。
4.2.3 シグナル処理の概念
イベントによってシグナルが最初に発生した場合,プロセスに対してシグナルが生成される ( またはプロセスにシグナルが送信される ) と言うことができます。このようなイベントとしては,ハードウェア障害の検出,タイマの満了,端末での動作, killの起動などがあります。場合によっては,同じイベントで複数のプロセスに対してシグナルが生成されることもあります。
各シグナルに対して各プロセスが実行する動作は,システムで定義されています。プロセスとシグナルに対して適切な動作が実行されたときに,シグナルはプロセスに配布されると言うこともできます。
シグナルが生成されてから配布されるまでの間,シグナルは保留状態であると言うことができます。通常,アプリケーションでこの間隔を検出することはできません。しかし,シグナルがプロセスに配布されないように ブロックすることはできます。
各プロセスにはシグナル・マスクがあり,現在配布されないようにブロックされているシグナルのセットが定義されます。プロセスのシグナル・マスクはその親のシグナル・マスクから初期化されます。 sigaction, sigprocmask, sigsuspend関数はシグナル・マスクの操作を制御します。
シグナルに対する応答としてどの動作を実行するかの判断は,シグナルの配布時に行われるため,シグナルが生成された後で変更することができます。この判断は,シグナルがもともと生成された手段とは無関係です。保留状態のシグナルが後で再び生成された場合,そのシグナルが 2 回以上配布されるかどうかはインプリメンテーションに応じて異なります。 HP C RTL ではシグナルは 1 回だけ配布されます。同時に保留状態になっている複数のシグナルがプロセスに配布される順序は不定です。
4.2.4 シグナル・アクション
このセクションの説明は, sigaction, signal, sigvec, ssignal関数に適用されます。
シグナルに割り当てることができるアクションは次の 3 種類です。
SIG_DFL
SIG_IGN
関数を指すポインタ
最初は, mainルーチンのエントリの前で,すべてのシグナルが SIG_DFL または SIG_IGN に設定されます ( exec関数を参照)。これらの値によって設定される動作は次のとおりです。
SIG_DFL --- シグナル固有のデフォルト動作。
- 本書で定義しているシグナルのデフォルト動作は, <signal.h>に指定されています。
- デフォルト動作がプロセスの停止である場合,そのプロセスの実行が一時停止されます。プロセスが停止すると,親プロセスで SA_NOCLDSTOP フラグが設定されていない限り, SIGCHLD シグナルが親プロセスに対して生成されます。プロセスが停止されている間,そのプロセスに送信される追加シグナルは,プロセスが続行されるまで配布されません。ただし, SIGKILL は例外で,このシグナルは常にシグナルを受け取ったプロセスを終了します。孤立しているプロセス・グループのメンバであるプロセスは,SIGSTOP,SIGTTIN, SIGTTOU シグナルに対する応答として停止することができません。これらのシグナルのいずれかが配布されることによってこのようなプロセスが停止される場合,シグナルは破棄されます。
- 保留状態のシグナルに対して,シグナルの動作が SIG_DFL に設定されていて,そのデフォルト動作がシグナルの無視である場合 (たとえば SIGCHLD),シグナルがブロックされているかどうかとは無関係に,保留状態のシグナルは破棄されます。
SIG_IGN --- シグナルを無視します。
- シグナルの配布はプロセスに影響を与えません。 killまたは raise関数によって生成されたものではない SIGFPE,SIGILL,SIGSEGV シグナルを無視した後,プロセスの動作は未定義です。
- SIGKILL または SIGSTOP シグナルの動作を SIG_IGN に設定することはできません。
- 保留状態のシグナルに対してシグナルの動作を SIG_IGN に設定すると,保留状態のシグナルは,ブロックされているかどうかとは無関係に破棄されます。
- プロセスで SIGCHLD シグナルの動作が SIG_IGN に設定されると,動作は不定になります。
関数に対するポインタ --- シグナルを検出します。
- シグナルの配布時に,シグナルを受け取るプロセスが指定されたアドレスでシグナル検出関数を実行します。シグナル検出関数から戻った後,シグナルを受信したプロセスは割り込まれた位置から実行を再開します。
- シグナル検出関数は次のように指定します。
void func(int signo);
ただし,func は指定されたシグナル検出関数であり, signo は配布するシグナルのシグナル番号です。- killまたは raiseによって生成されたものではない SIGFPE,SIGKILL,SIGSEGV シグナルに対するシグナル検出関数から正常に戻った後のプロセスの動作は未定義です。
- SIGKILL および SIGSTOP シグナルをプロセスで検出することはできません。
- 終了した子プロセスがあり,その子プロセスを待機していないときに, SIGCHLD シグナルに対してシグナル検出関数をプロセスで設定した場合, SIGCHLD シグナルがその子プロセスを示すように生成されるかどうかは不定です。
ここでは, HP C RTL のシグナル処理が OpenVMS の例外処理でどのようにインプリメントされ,どのように相互に影響するかについて説明します。このセクションの説明を読むと, HP C RTL のシグナル処理と競合しない OpenVMS 例外ハンドラを作成することができます。 OpenVMS の例外処理の詳細については,『OpenVMS Procedure Calling and Condition Handling Standard』を参照してください。
HP C RTL では, OpenVMS の例外によってシグナルをインプリメントしています。 gsignalまたは raiseを呼び出すと,シグナル番号が特定の OpenVMS 例外に変換され, LIB$SIGNAL の呼び出しで使用されます。ユーザ・エラーによって発生した OpenVMS 例外を検出し,それを対応する UNIX シグナルに変換するには,この機能が必要です。たとえば,NULL ポインタへの書き込みによって発生する ACCVIO は, SIGBUS または SIGSEGV シグナルに変換されます。
表 4-4 および表 4-5 は, HP C RTL のシグナル名,対応する OpenVMS VAX および OpenVMS Alpha 例外,シグナルを生成するイベント, gsignal関数および raise関数で使用するための省略可能なシグナル・コードを示しています。
on
名前 | OpenVMS 例外 | シグナルを生成するイベント | コード |
---|---|---|---|
SIGABRT | SS$_OPCCUS | abort 関数 | -- |
SIGALRM | SS$_ASTFLT | alarm 関数 | -- |
SIGBUS | SS$_ACCVIO | アクセス違反 | -- |
SIGBUS | SS$_CMODUSER | 変更モード・ユーザ | -- |
SIGCHLD | C$_SIGCHLD | 子プロセスの停止 | -- |
SIGEMT | SS$_COMPAT | 互換性モード・トラップ | -- |
SIGFPE | SS$_DECOVF | 10 進オーバフロー・トラップ | FPE_DECOVF_TRAP |
SIGFPE | SS$_FLTDIV | 0 による浮動小数点/10 進数除算 | FPE_FLTDIV_TRAP |
SIGFPE | SS$_FLTDIV_F | 0 による浮動小数点除算フォルト | FPE_FLTDIV_FAULT |
SIGFPE | SS$_FLTOVF | 浮動小数点オーバフロー・トラップ | FPE_FLTOVF_TRAP |
SIGFPE | SS$_FLTOVF_F | 浮動小数点オーバフロー・フォルト | FPE_FLTOVF_FAULT |
SIGFPE | SS$_FLTUND | 浮動小数点アンダフロー・トラップ | FPE_FLTUND_TRAP |
SIGFPE | SS$_FLTUND_F | 浮動小数点アンダフロー・フォルト | FPE_FLTUND_FAULT |
SIGFPE | SS$_INTDIV | 0 による整数除算 | FPE_INTDIV_TRAP |
SIGFPE | SS$_INTOVF | 整数オーバフロー | FPE_INTOVF_TRAP |
SIGFPE | SS$_SUBRNG | 添字の範囲 | FPE_SUBRNG_TRAP |
SIGHUP | SS$_HANGUP | データ・セット・ハングアップ | -- |
SIGILL | SS$_OPCDEC | 予約命令 | ILL_PRIVIN_FAULT |
SIGILL | SS$_RADRMOD | 予約アドレッシング | ILL_RESAD_FAULT |
SIGILL | SS$_ROPRAND | 予約オペランド | ILL_RESOP_FAULT |
SIGINT | SS$_CONTROLC | OpenVMS Ctrl/C 割り込み | -- |
SIGIOT | SS$_OPCCUS | カスタマ予約 op コード | -- |
SIGKILL | SS$_ABORT | 外部シグナルのみ | -- |
SIGQUIT | SS$_CONTROLY | raise 関数 | -- |
SIGPIPE | SS$_NOMBX | メールボックスなし | -- |
SIGSEGV | SS$_ACCVIO | 長さ違反 | -- |
SIGSEGV | SS$_CMODUSER | 変更モード・ユーザ | -- |
SIGSYS | SS$_BADPARAM | システム呼び出しに対する不正な引数 | -- |
SIGTERM | インプリメントされていない | -- | -- |
SIGTRAP | SS$_TBIT | TBIT トレース・トラップ | -- |
SIGTRAP | SS$_BREAK | ブレークポイント・フォルト命令 | -- |
SIGUSR1 | C$_SIGUSR1 | raise 関数 | -- |
SIGUSR2 | C$_SIGUSR2 | raise 関数 | -- |
SIGWINCH 1 | C$_SIGWINCH 2 | raise 関数 | -- |
signalまたは sigvecによって設定したシグナル・ハンドラを呼び出すために, HP C RTL は,プログラムの main ルーチンに OpenVMS 例外ハンドラを配置することにより,シグナルに対応する OpenVMS 例外をインターセプトします。プログラムに main関数がある場合は,この例外ハンドラが自動的に設定されます。 main関数がない場合や, main 関数が HP C 以外の言語で作成されている場合は,このハンドラを設定するために VAXC$CRTL_INITルーチンを呼び出す必要があります。
前へ | 次へ | 目次 | 索引 |