signal(C RTL)

提供: Appmethod Topics
移動先: 案内検索

signal.h:インデックス への移動


ヘッダーファイル

signal.h

カテゴリ

プロセス制御ルーチン

プロトタイプ

void (_USERENTRY *signal(int sig, void (_USERENTRY *func)(int sig[, int subcode])))(int);

説明

シグナル処理アクションを指定します。

signal は,シグナル番号 sig が受け取った後で,それをどのように処理するかを決定します。ユーザー指定のハンドラルーチン(引数 func で指定される)をインストールするか,signal.h で定義されているハンドラ SIG_DFL および SIG_IGN のいずれかを使用します。関数 func は,_USERENTRY 呼び出し規約を使って宣言する必要があります。

シグナル(浮動小数点など)を捕捉するルーチンは,シグナルのクリアも行います。続けてシグナルを受信するには,再度 signal を呼び出して,シグナルハンドラを再インストールする必要があります。

SIG_DFL

プログラムを終了します。

SIG_ERR

シグナルからエラーが返されたことを示します。

SIG_IGN

この型のシグナルを無視します。



次の表に,シグナルの型とそれらのデフォルトの動作を示します。

SIGBREAK

キーボードがローモードである必要があります。

SIGABRT

異常終了。デフォルトのアクションは,_exit(3) の呼び出しと同じです。

SIGFPE

ゼロ除算演算エラー,無効な操作など。デフォルトのアクションは,_exit(1) の呼び出しと同じです。

SIGILL

不正な操作。デフォルトのアクションは,_exit(1) の呼び出しと同じです。

SIGINT

Ctrl-C 割り込み。デフォルトのアクションは,_exit(3) の呼び出しと同じです。

SIGSEGV

ストレージへの不正なアクセス。デフォルトのアクションは,_exit(1) の呼び出しと同じです。

SIGTERM

プログラムの終了の要求。デフォルトのアクションは,_exit(1) の呼び出しと同じです。

ユーザー定義シグナルは,raise の呼び出しによってのみ生成されます。デフォルトのアクションはシグナルを無視することです。



signal.h には,sig_atomic_t という型が定義されています。これは,非同期割り込みが存在するときに,プロセッサがアトミックにロードまたは保存できる最大の整数の型です(32 ビットの整数 -- Borland C++ 整数)。

raise 関数または外部イベントによってシグナルが生成されると,次の 2 つの動作が行われます。

  • そのシグナルに対するユーザー指定のハンドラがインストールされている場合は,そのシグナルの型に対するアクションが SIG_DFL に設定されます。
  • そのシグナルの型をパラメータとして使用して,ユーザー指定の関数が呼び出されます。

ユーザー指定のハンドラ関数は,return で終了するか,abort,_exit,exit,または longjmp を呼び出して終了できます。ハンドラ関数によってさらにシグナルを受信して処理できるようにするには,ハンドラ関数から再度 signal を呼び出す必要があります。

Borland C++ は,シグナルの型が SIGFPE,SIGSEGV,または SIGILL の場合に,ANSI C の拡張機能を実装しています。ユーザー指定のハンドラ関数は,1 つまたは 2 つの追加パラメータを付けて呼び出すことができます。raise 関数の明示的な呼び出しによって SIGFPE,SIGSEGV,または SIGILL が生成された場合は,ユーザー指定のハンドラが 1 つの追加パラメータを付けて呼び出されます。このパラメータは,明示的に呼び出されるハンドラを指定する整数です。SIGFPE,SIGSEGV,および SIGILL に対する明示的なアクティブ化の値は次のとおりです。

メモ:  これらの型の宣言は,float.h で定義されています。

SIGFPE

FPE_EXPLICITGEN

SIGSEGV

SEGV_EXPLICITGEN

SIGILL

ILL_EXPLICITGEN



浮動小数点例外によって SIGFPE が生成された場合は,シグナルの FPE_xxx 型を指定する追加パラメータを付けてユーザーハンドラが呼び出されます。プロセッサ例外の結果として SIGSEGV,SIGILL,または整数関連の SIGFPE シグナル(FPE_INTOVFLOW または FPE_INTDIV0)が生成された場合は,2 つの追加パラメータを付けてユーザーハンドラが呼び出されます。

1. SIGFPE,SIGSEGV,または SIGILL 例外型(これらの型については,float.h を参照)。最初のパラメータは,通常の ANSI シグナル型です。

2. ユーザー指定のハンドラを呼び出した割り込みハンドラのスタックへの整数ポインタ。このポインタは,例外の発生時に保存されたプロセッサレジスタのリストを指します。レジスタは,割り込み関数のパラメータと同じ順序(EBP,EDI,ESI,EDS,ES,EDX,ECX,EBX,EAX,EIP,CS,EFL)です。ハンドラから返るときにレジスタ値を変更するには,このリスト内の位置の 1 つを変更します。

たとえば,新しい SI 値を返すには,次のようにします。

*((int*)list_pointer + 2) = new_SI_value;

このように,ハンドラで任意のレジスタを調べたり,調整することができます。

次の SIGFPE 型のシグナルが発生(または生成)する可能性があります。これらは,80x87 ファミリーが検出可能な例外と,メイン CPU の「INTEGER DIVIDE BY ZERO」および「INTERRUPT ON OVERFLOW」に対応します。これらの宣言は float.h にあります。

FPE_INTOVFLOW

OF フラグを設定した INTO の実行

FPE_INTDIV0

ゼロによる整数の除算

FPE_INVALID

無効な操作

FPE_ZERODIVIDE

ゼロによる除算

FPE_OVERFLOW

数値オーバーフロー

FPE_UNDERFLOW

数値アンダーフロー

FPE_INEXACT

精度

FPE_EXPLICITGEN

ユーザープログラムによる raise(SIGFPE) の実行

FPE_STACKFAULT

浮動小数点のスタックオーバーフローまたはアンダーフロー

FPE_STACKFAULT

スタックオーバーフロー



FPE_INTOVFLOW および FPE_INTDIV0 シグナルは整数演算によって生成され,その他は浮動小数点演算によって生成されます。浮動小数点例外が生成されるかどうかは,コプロセッサコントロールワードに依存します。これは,_control87 で変更できます。非正規化例外は,Borland C++ によって処理され,シグナルハンドラには渡されません。

次の SIGSEGV 型のシグナルが発生する可能性があります。

SEGV_BOUND

範囲制約例外

SEGV_EXPLICITGEN

raise(SIGSEGV) が実行された



次の SIGILL 型のシグナルが発生する可能性があります。

ILL_EXECUTION

不正な操作の試行

ILL_EXPLICITGEN

raise(SIGILL) が実行された



シグナルの型が SIGFPE,SIGSEGV,または SIGILL であり,浮動小数点プロセッサの状態の破損,整数除算の結果の誤り,オーバーフローしてはならない操作のオーバーフロー,範囲指令の失敗,または不正な操作の試行があった場合,シグナルハンドラからのリターンは一般に推奨できません。リターンが妥当になるのは,ハンドラがレジスタを変更して,妥当な戻りコンテキストが存在する場合,またはシグナルの型が,シグナルが明示的に生成されたことを示している場合(たとえば,FPE_EXPLICITGEN,SEGV_EXPLICITGEN,または ILL_EXPLICITGEN)だけです。一般に,この場合はエラーメッセージを出力し,_exit,exit,または abort を使ってプログラムを終了します。ほかの条件下でリターンを実行した場合,通常,プログラムのアクションは予想できません。

メモ:  マルチスレッドプログラムで signal 関数を使用する場合は,特に注意が必要です。SIGINT,SIGTERM,および SIGBREAK シグナルは,Win32 以外のアプリケーションのメインスレッド(スレッド 1)でのみ使用できます。このシグナルの 1 つが発生すると,そのとき実行されているスレッドが中止され,スレッド 1 によって設定されたシグナルハンドラ(ある場合)に制御が移されます。その他のシグナルは任意のスレッドで処理できます。

メモ:  セマフォデッドロックが発生する可能性があるため,シグナルハンドラで C++ ランタイムライブラリ関数を使用してはなりません。かわりに,ハンドラは単純にフラグを設定するか,セマフォを送信し,即座に戻る必要があります。

戻り値

成功した場合,signal は,指定されたシグナル型に対する,前のハンドラルーチンへのポインタを返します。

エラーが発生した場合は SIG_ERR を返し,外部変数 errno は EINVAL に設定されます。



 /* シグナルの例 */
 /*
     この例では,SIGFPE のシグナルハンドラルーチンをインストールし,
     整数オーバーフロー条件を捕捉し,AX レジスタの調整を行い,
     戻ります。このプログラムを実行すると,コンピュータが
     クラッシュする可能性があります。また,使用しているメモリモデルによっては
     実行時エラーが発生します
 */
 #pragma inline
 #include <stdio.h>
 #include <signal.h>
 #ifdef __cplusplus
    typedef void (*fptr)(int);
 #else
    typedef void (*fptr)();
 #endif
 void Catcher(int *reglist)
 {
    signal(SIGFPE, (fptr)Catcher);  //  ******シグナルハンドラを再インストールします
    printf("Caught it!\n"); *(reglist + 8) = 3; /* AX = 3 を返します */
 }
 int main(void)
 {
    signal(SIGFPE, (fptr)Catcher);  /* Catcher を適切な型にキャストします */
    asm     mov     ax,07FFFH       /* AX = 32767 */
    asm     inc     ax              /* オーバーフローになります */
    asm     into                    /* ハンドラをアクティブにします */
    /* リターン時にハンドラは AX を 3 に設定します。これを行わないと,
       「dec」指令の後で次の「into」を実行したときに,別の例外が
       発生する可能性があります */
    asm     dec     ax              /* オーバーフローになりません */
    asm     into                    /* アクティブにしません */
    return 0;
 }



移植性



POSIX Win32 ANSI C ANSI C++

+

+

+

+