sigaction - システムコールの説明 - Linux コマンド集 一覧表
名前
sigaction - シグナルの動作の確認と変更
書式
#include <signal.h>
int sigaction(int
signum
, const struct sigaction *
act
,
struct sigaction *
oldact
);
説明
sigaction ()システムコールは、特定のシグナルを受信した際の プロセスの動作を変更するのに使用される。
signum には、 SIGKILL と SIGSTOP 以外の有効なシグナルをどれでも指定できる。
act が NULL 以外であれば、シグナル signum の新しい動作 (action) として act が設定される。 oldact が NULL でなければ、今までの動作が oldact に格納される。
sigaction
構造体は以下のような感じに定義される。
struct sigaction { void (*sa_handler)(int); void (*sa_sigaction)(int, siginfo_t *, void *); sigset_t sa_mask; int sa_flags; void (*sa_restorer)(void); }
アーキテクチャによっては共用体 (union) が用いられており、その場合には sa_handler と sa_sigaction の両方を同時に割り当てることはできない。
sa_restorer 要素は廃止予定であり使用すべきではない。 POSIX には sa_restorer 要素に関する規定はない。
sa_handler は signum に対応する動作を指定するもので、 デフォルトの動作を行う SIG_DFL 、そのシグナルを無視する SIG_IGN 、シグナルハンドラ関数へのポインタが設定できる。 シグナルハンドラ関数の引き数は一つであり、シグナル番号が引き数として 渡される。
sa_flags に SA_SIGINFO が指定された場合、 ( sa_handler ではなく) sa_sigaction により signum に対応するシグナルハンドル関数が指定される。 指定される関数は、最初の引き数としてシグナル番号を、 二番目の引き数として siginfo_t へのポインタを、三番目の引き数として (void * にキャストした) ucontext_t へのポインタを受けとる。
sa_mask は、シグナル・ハンドラ実行中に禁止 (block) するシグナルのマスクを表す。 さらに、 SA_NODEFER フラグが指定されていない場合は、ハンドラを起動するきっかけとなる シグナルにも sa_mask が適用される。
sa_flags
はシグナル・ハンドラの動作を変更するためのフラグの集合を指定する。
sa_flags
には、以下に示すフラグの (0個以上の) 論理和をとったものを指定する。
- SA_NOCLDSTOP
- signum が SIGCHLD の場合、 子プロセスが停止したり (子プロセスが SIGSTOP , SIGTSTP , SIGTTIN , SIGTTOU を受けたとき) 再開したり (子プロセスが SIGCONT を受けたとき) したときに SIGCHLD の通知を受けない。
- SA_NOCLDWAIT
- (Linux 2.6 以降) signum が SIGCHLD の場合、子プロセスが終了したときに 子プロセスをゾンビプロセスに変化させない ( waitpid (2)も参照)。
- SA_RESETHAND
- シグナルハンドラが呼ばれる度に、シグナルの動作をデフォルトに戻す。 SA_ONESHOT はこのフラグと同じ意味だが、廃止されており、非標準である。
- SA_ONSTACK
- sigaltstack (2) で提供される別のシグナル・スタックでシグナルハンドラを呼び出す。 別のシグナル・スタックが利用可能でなければ、デフォルトのスタックが 使用される。
- SA_RESTART
- いくつかのシステムコールをシグナルの通知の前後で再開できるようにして、 BSD シグナル方式 (semantics) と互換性のある動作を提供する。
- SA_NODEFER
- それ自身のシグナル・ハンドラーの内部にいる時でも そのシグナルをマスクしないようにする。 SA_NOMASK はこのフラグと同じ意味だが、廃止されており、非標準である。
- SA_SIGINFO
-
シグナルハンドラは一つではなく、三つの引き数を持つ。この場合は
sa_handler
のかわりに
sa_sigaction
を設定しなければならない
(
sa_sigaction
フィールドは Linux 2.1.86 で追加された)。
sa_sigaction のパラメータ siginfo_t は以下の要素を持つ構造体である:
siginfo_t { int si_signo; /* Signal number */ int si_errno; /* An errno value */ int si_code; /* Signal code */ pid_t si_pid; /* Sending process ID */ uid_t si_uid; /* Real user ID of sending process */ int si_status; /* Exit value or signal */ clock_t si_utime; /* User time consumed */ clock_t si_stime; /* System time consumed */ sigval_t si_value; /* Signal value */ int si_int; /* POSIX.1b signal */ void * si_ptr; /* POSIX.1b signal */ void * si_addr; /* Memory location which caused fault */ int si_band; /* Band event */ int si_fd; /* File descriptor */ }
si_signo , si_errno , si_code は全てのシグナルに対して定義されている ( si_signo は Linux では使用されない)。 構造体の残りの部分は、共用体 (union) になっているかもしれない。 その場合は該当するシグナルにおいて意味のあるフィールドのみを読み込む ことができる。 POSIX.1b シグナルと SIGCHLD は si_pid と si_uid を設定する。 .B SIGCHLDはさらに si_status , si_utime , si_stime も設定する。 si_int と si_ptr は POSIX.1b シグナルの送信者によって指定される。 SIGILL , SIGFPE , SIGSEGV , SIGBUS は si_addr にエラーが発生したアドレスを設定する。 SIGPOLL は si_band と si_fd を設定する。
si_code は、そのシグナルが送信された理由を示す。これは値でありビットマスクではない。 以下の表にはどのシグナルの場合でも使用できる値を記載している: .TS tab(:) allbox; c s l l. si_code Value:Signal origin SI_USER:kill(), sigsend(), or raise() SI_KERNEL:The kernel SI_QUEUE:sigqueue() SI_TIMER:POSIX timer expired SI_MESGQ:POSIX message queue state changed (since Linux 2.6.6) SI_ASYNCIO:AIO completed SI_SIGIO:queued SIGIO SI_TKILL:tkill() or tgkill() (since Linux 2.4.19)
.TS tab(:) allbox; c s l l. SIGILL ILL_ILLOPC:illegal opcode ILL_ILLOPN:illegal operand ILL_ILLADR:illegal addressing mode ILL_ILLTRP:illegal trap ILL_PRVOPC:privileged opcode ILL_PRVREG:privileged register ILL_COPROC:coprocessor error ILL_BADSTK:internal stack error
.TS tab(:) allbox; c s l l. SIGFPE FPE_INTDIV:integer divide by zero FPE_INTOVF:integer overflow FPE_FLTDIV:floating point divide by zero FPE_FLTOVF:floating point overflow FPE_FLTUND:floating point underflow FPE_FLTRES:floating point inexact result FPE_FLTINV:floating point invalid operation FPE_FLTSUB:subscript out of range
.TS tab(:) allbox; c s l l. SIGSEGV SEGV_MAPERR:address not mapped to object SEGV_ACCERR:invalid permissions for mapped object
.TS tab(:) allbox; c s l l. SIGBUS BUS_ADRALN:invalid address alignment BUS_ADRERR:non-existent physical address BUS_OBJERR:object specific hardware error
.TS tab(:) allbox; c s l l. SIGTRAP TRAP_BRKPT:process breakpoint TRAP_TRACE:process trace trap
.TS tab(:) allbox; c s l l. SIGCHLD CLD_EXITED:child has exited CLD_KILLED:child was killed CLD_DUMPED:child terminated abnormally CLD_TRAPPED:traced child has trapped CLD_STOPPED:child has stopped CLD_CONTINUED:stopped child has continued (since Linux 2.6.9)
.TS tab(:) allbox; c s l l. SIGPOLL POLL_IN:data input available POLL_OUT:output buffers available POLL_MSG:input message available POLL_ERR:i/o error POLL_PRI:high priority input available POLL_HUP:device disconnected
返り値
sigaction ()は成功すれば 0 を返し、エラーならば -1 を返す。
エラー
- EFAULT
- act か oldact が指しているメモリが正しいプロセスのアドレス空間にない。
- EINVAL
- 無効なシグナルが指定された。補足 (catch) したり無視したりできない シグナルである SIGKILL や SIGSTOP に対する動作を変更しようとした場合にも発生する。
注意
POSIX では、kill () や raise () 関数で生成できないシグナル SIGFPE, SIGILL, SIGSEGV を無視 (ignore) した場合、その後の動作は未定義である。 ゼロによる整数割り算の結果は未定義となる。 アーキテクチャーによっては、このとき SIGFPE シグナルが生成される。 (同様に負の最大整数を -1 で割ると SIGFPE が生成されるかもしれない) このシグナルを無視すると無限ループに陥るかもしれない。
POSIX.1-1990 では SIGCHLD に SIG_IGN を設定することを認めていない。 POSIX.1-2001 では認められており、 SIGCHLD を無視することでゾンビプロセスの生成を防止することができる ( wait (2)を参照)。 さらに、BSD と SystemV では SIGCHLD を無視した際の動作が異なっている。 そのため、完全に移植性がある方法で、終了した子プロセスがゾンビにならないこと を保証するには、 SIGCHLD シグナルを補足し、 wait (2) などを実行するしかない。
POSIX.1-1990 の仕様では SA_NOCLDSTOP のみが定義されている。 POSIX.1-2001 では SA_NOCLDWAIT , SA_RESETHAND , SA_NODEFER , SA_SIGINFO が追加された。 Unix の古い実装で動かすアプリケーションで、 他の sa_flags フラグを使用すると移植性が下がる。
SA_SIGINFO フラグは Linux 2.2 からサポートされるようになった。
SA_RESETHAND フラグは SVr4 の同じ名前のフラグと互換性がある。
SA_NODEFER フラグは 1.3.9 以降のカーネルでは同じ名前の SVr4 のフラグと互換性がある。 ぞれ以前の Linux カーネルの実装では、このフラグを設定しているシグナル だけでなく、どのシグナルでも受けることを許していた (実際には sa_mask の設定により無効にできる)。
sigaction ()の二番目の引き数に NULL を指定して呼び出すと、現在のシグナルハンドラを確認する ことができる。また、二番目と三番目の引き数を NULL にて呼び出すことで、 指定されたシグナルが現在のマシンで使えるかどうかチェックできる。
SIGKILL や SIGSTOP を ( sa_mask に指定して) 禁止することはできない。 禁止しようとしても黙って無視される。
シグナル集合の操作に関する詳細は sigsetops (3) を参照すること。
バグ
2.6.13 以前のカーネルでは、 sa_flags に SA_NODEFER を指定した場合、 ハンドラが実行中に配送されたシグナル自身がマスクされなくなるだけでなく、 sa_mask に指定されたシグナルもマスクされなくなる。 このバグは、カーネル 2.6.14 で修正された。
準拠
POSIX.1-2001, SVr4.
非公式
SA_SIGINFO が導入される前は、 "struct sigcontext" 型の二番目の引き数と一緒に sa_handler を使用することで、 いくつかの追加の情報を入手することができた。 詳細についてはカーネルソースの関連部分を見てほしい。 現在はこの使用法は廃止されている。