SIGNAL(7) | Linux Programmer's Manual | SIGNAL(7) |
名前
signal -シグナルの概要説明
Linux は POSIX 信頼シグナル (reliable signal;以後 "標準シグナル"と表記) と POSIX リアルタイムシグナルの両方に対応している。シグナル処理方法
シグナルはそれぞれ現在の「処理方法 (disposition)」を保持しており、この処理方法によりシグナルが配送された際にプロセスがどのような振舞いをするかが決まる。- Term
- デフォルトの動作はプロセス終了。
- Ign
- デフォルトの動作はこのシグナルの無視。
- Core
- デフォルトの動作はプロセス終了とコアダンプ出力 ( core(5) 参照)。
- Stop
- デフォルトの動作はプロセスの一時停止。
- Cont
- デフォルトの動作は、プロセスが停止中の場合にその実行の再開。
プロセスは、 sigaction(2) や signal(2) を使って、シグナルの処理方法を変更することができる ( signal(2) の方がシグナルハンドラを設定する際の移植性が低い;詳細は signal(2) を参照)。シグナルの配送時に起こる動作としてプロセスが選択できるのは、次のいずれか一つである。デフォルトの動作を実行する、シグナルを無視する、 シグナルハンドラ (signal handler) でシグナルを捕捉する。シグナルハンドラとは、シグナル配送時に自動的に起動されるプログラマ定義の関数である。 (デフォルトでは、シグナルハンドラは通常のプロセスのスタック上で起動される。シグナルハンドラが代替スタック (alternate stack) を使用するように設定することもできる。代替スタックを使用するように設定する方法と、どのような際に代替スタックが役に立つかについての議論については sigaltstack(2) を参照のこと。
シグナルの処理方法はプロセス単位の属性である。マルチスレッドのアプリケーションでは、あるシグナルの処理方法は全てのスレッドで同じである。
fork(2) 経由で作成された子プロセスは、親プロセスのシグナルの処理方法のコピーを継承する。 execve(2) の前後で、ハンドラが設定されているシグナルの処理方法はデフォルトにリセットされ、無視が設定されているシグナルの処理方法は変更されずそのままとなる。
シグナルの送信
以下のシステムコールとライブラリ関数を使って、呼び出し者はシグナルを送信することができる。- raise(3)
- 呼び出したスレッドにシグナルを送る。
- kill(2)
- 指定されたプロセスや、指定されたプロセスグループの全メンバー、システムの全プロセスにシグナルを送る。
- killpg(2)
- 指定されたプロセスグループの全メンバーにシグナルを送る。
- pthread_kill(3)
- 呼び出し者と同じプロセス内の指定された POSIX スレッドにシグナルを送る。
- tgkill(2)
- 指定されたプロセス内の指定されたスレッドにシグナルを送る (このシステムコールを使って pthread_kill(3) は実装されている)。
- sigqueue(3)
- 指定されたプロセスに付属データとともにリアルタイムシグナルを送る。
シグナルが捕捉されるのを待つ
以下のシステムコールを使って、シグナルが捕捉されるまで呼び出したプロセスやスレッドの実行を中断 (suspend) することができる (ハンドラが設定されていないシグナルによりそのプロセスが終了した場合にも実行の停止は終了する)。- pause(2)
- 何かシグナルが捕捉されるまで実行を停止する。
- sigsuspend(2)
- 一時的にシグナルマスク (下記参照) を変更し、マスクされていないシグナルのいずれかが捕捉されるまで実行を中断する。
シグナルの同期受信
シグナルハンドラ経由でシグナルを非同期 (asynchronously) で捕捉する以外にも、シグナルを同期 (synchronously) して受け付けることもできる。同期して受け付けるとは、シグナルが配送されるまで実行を停止 (block) するということである。シグナルを受け付けた際に、カーネルはそのシグナルに関する情報を呼び出し者に返す。これを行う一般的な方法が二つある。- *
- sigwaitinfo(2), sigtimedwait(2), sigwait(3) は、指定されたシグナル集合のシグナルの一つが配送されるまで実行を中断する。どのシステムコールや関数でも、配送されたシグナルに関する情報が返される。
- *
- signalfd(2) が返すファイルディスクリプタを使うと、呼び出し元に配送されたシグナルに関する情報を読み出すことができる。このファイルディスクリプタからの read(2) は、 signalfd(2) の呼び出し時に指定されたシグナル集合のシグナルの一つが呼び出し元に配送されるまで停止 (block) する。 read(2) が返すバッファにはシグナルに関する情報を格納した構造体が入っている。
シグナルマスクと処理待ちシグナル
シグナルは ブロック (block) されることがある。ブロックされると、そのシグナルはその後ブロックを解除されるまで配送されなくなる。シグナルが生成されてから配送されるまでの間、そのシグナルは 処理待ち (pending) であると呼ばれる。標準シグナル
Linux は以下に示す標準シグナルに対応している。シグナル番号の一部はアーキテクチャ依存であり、"値"欄に示す通りである。 (3つの値が書かれているものは、 1つ目が alpha と sparc で通常有効な値、真ん中が x86, arm や他のほとんどのアーキテクチャでの有効な値、最後が mips での値である。 (parisc での値は記載されて いない。 parisc でのシグナル番号は Linux カーネルソースを参照してほしい)。-はそのアーキテクチャにおいて対応するシグナルがないことを示す。)シグナル | 値 | 動作 | コメント |
SIGHUP | 1 | Term | 制御端末(controlling terminal)のハングアップ検出、 |
または制御しているプロセスの死 | |||
SIGINT | 2 | Term | キーボードからの割り込み (Interrupt) |
SIGQUIT | 3 | Core | キーボードによる中止 (Quit) |
SIGILL | 4 | Core | 不正な命令 |
SIGABRT | 6 | Core | abort(3) からの中断 (Abort) シグナル |
SIGFPE | 8 | Core | 浮動小数点例外 |
SIGKILL | 9 | Term | Kill シグナル |
SIGSEGV | 11 | Core | 不正なメモリ参照 |
SIGPIPE | 13 | Term | パイプ破壊: |
読み手の無いパイプへの書き出し | |||
SIGALRM | 14 | Term | alarm(2) からのタイマーシグナル |
SIGTERM | 15 | Term | 終了 (termination) シグナル |
SIGUSR1 | 30,10,16 | Term | ユーザ定義シグナル 1 |
SIGUSR2 | 31,12,17 | Term | ユーザ定義シグナル 2 |
SIGCHLD | 20,17,18 | Ign | 子プロセスの一時停止 (stop) または終了 |
SIGCONT | 19,18,25 | Cont | 一時停止 (stop) からの再開 |
SIGSTOP | 17,19,23 | Stop | プロセスの一時停止 (stop) |
SIGTSTP | 18,20,24 | Stop | 端末より入力された一時停止 (stop) |
SIGTTIN | 21,21,26 | Stop | バックグランドプロセスの端末入力 |
SIGTTOU | 22,22,27 | Stop | バックグランドプロセスの端末出力 |
シグナル | 値 | 動作 | コメント |
SIGBUS | 10,7,10 | Core | バスエラー (不正なメモリアクセス) |
SIGPOLL | Term | ポーリング可能なイベント (Sys V)。 | |
SIGIO と同義 | |||
SIGPROF | 27,27,29 | Term | profiling タイマの時間切れ |
SIGSYS | 12,31,12 | Core | ルーチンへの引き数が不正 (SVr4) |
SIGTRAP | 5 | Core | トレース/ブレークポイントトラップ |
SIGURG | 16,23,21 | Ign | ソケットの緊急事態 (urgent condition) (4.2BSD) |
SIGVTALRM | 26,26,28 | Term | 仮想アラームクロック (4.2BSD) |
SIGXCPU | 24,24,30 | Core | CPU時間制限超過 (4.2BSD) |
SIGXFSZ | 25,25,31 | Core | ファイルサイズ制限の超過 (4.2BSD) |
シグナル | 値 | 動作 | コメント |
SIGIOT | 6 | Core | IOT トラップ。 SIGABRT と同義 |
SIGEMT | 7,-,7 | Term | |
SIGSTKFLT | -,16,- | A | 数値演算プロセッサにおけるスタックフォルト (未使用) |
SIGIO | 23,29,22 | Term | 入出力が可能になった (4.2BSD) |
SIGCLD | -,-,18 | Ign | SIGCHLD と同義 |
SIGPWR | 29,30,19 | Term | 電源喪失 (Power failure) (System V) |
SIGINFO | 29,-,- | SIGPWR と同義 | |
SIGLOST | -,-,- | Term | ファイルロックが失われた (未使用) |
SIGWINCH | 28,28,20 | Ign | ウィンドウリサイズシグナル (4.3BSD, Sun) |
SIGUNUSED | -,31,- | Core | SIGSYS と同義 |
リアルタイムシグナル
Linux はリアルタイムシグナルをサポートしている。リアルタイムシグナルは元々 POSIX.1b のリアルタイム拡張で定義されているものであり、現在では POSIX.1-2001 に含まれている。対応しているリアルタイムシグナルの範囲は、マクロ SIGRTMIN と SIGRTMAX で定義される。 POSIX.1-2001 では、少なくとも _POSIX_RTSIG_MAX (8) 個のリアルタイムシグナルに対応した実装が要求されている。Linux は、32 個の異なるリアルタイムシグナルに対応しており、その番号は 33 から 64 である。しかしながら、glibc の POSIX スレッド実装は、内部で 2個 (NPTL の場合) か 3個 (LinuxThreads の場合) のリアルタイムシグナルを使用しており ( pthreads(7) 参照)、 SIGRTMIN の値を適切に (34 か 35 に) 調整する。利用可能なリアルタイムシグナルの範囲は glibc のスレッド実装により異なるし (使用するカーネルと glibc により実行時にも変化する)、 UNIX システムの種類によっても異なる。したがって、プログラムでは「ハードコーディングした数字を使ってのリアルタイムシグナルの参照は決してすべきではなく」、代わりに SIGRTMIN+n の形で参照すべきである。また、 SIGRTMIN+n が SIGRTMAX を超えていないかのチェックを (実行時に) 適切に行うべきである。
標準シグナルと異なり、リアルタイムシグナルには事前に定義された意味はない。リアルタイムシグナルの全部をアプリケーションで定義した用途に使える。
ハンドリングしないリアルタイムシグナルのデフォルトの動作は受信したプロセスの終了である。
リアルタイムシグナルは以下の特徴がある:
- 1.
- リアルタイムシグナルは複数の実体をキューに入れることができる。一方、標準シグナルの場合、そのシグナルがブロックされている間に同じシグナルの複数のインスタンスが配送されても、 1 つだけがキューに入れられる。
- 2.
- シグナルが sigqueue(3) を用いて送信された場合、付属データ (整数かポインタ) をシグナルと共に送信できる。受信側プロセスが sigaction(2) に SA_SIGINFO フラグを指定してシグナルハンドラを設定した場合、このデータは siginfo_t 構造体の si_value フィールド経由でハンドラの第 2 引き数として渡され、利用することができる。さらに、この構造体の si_pid と si_uid フィールドでシグナルを送信したプロセスの PID と実ユーザ ID を得ることができる。
- 3.
- リアルタイムシグナルでは配送される順序が保証される。同じタイプのリアルタイムシグナルは送信された順番に到着する。異なるリアルタイムシグナルが一つのプロセスに送信された場合、番号の小さいシグナルから先に到着する。 (つまり小さい番号のシグナルが高い優先順位を持つ。) 対照的に、一つのプロセスに対して複数の標準シグナルが処理待ちとなった場合、これらのシグナルが配送される順序は不定である。
一つのプロセスに対して標準シグナルとリアルタイムシグナルの両方が処理待ちの場合、POSIX はどちらが先に配送されるかを規定していない。 Linux では、他の多くの実装と同様、このような場合には標準シグナルが優先される。
POSIX によれば、1 プロセス毎に最低 _POSIX_SIGQUEUE_MAX (32) 個のリアルタイムシグナルをキューに入れられるべきとしている。しかし、 Linux では違った実装になっている。カーネル 2.6.7 までは (2.6.7 を含む)、全プロセスでキューに入っているリアルタイムシグナルの数の合計についてシステム全体での制限がある。この制限は /proc/sys/kernel/rtsig-max ファイルで見ることができ、 (権限があれば) 変更もできる。関係するファイルとして、 /proc/sys/kernel/rtsig-nr を見ることで、いくつのリアルタイムシグナルが現在キューに入っているかを知ることができる。 Linux 2.6.8 で、これらの /proc 経由のインターフェースは、 RLIMIT_SIGPENDING リソース制限に置き換えられた。これは、キューに入るシグナル数に関してユーザ単位に上限を指定するものである。詳しくは setrlimit(2) を参照。
非同期シグナルで安全な関数 (async-signal-safe functions)
シグナルハンドラ関数には非常に注意しなければならない。他の場所の処理はプログラム実行の任意の箇所で中断される可能性があるためである。 POSIX には「安全な関数 (safe function)」という概念がある。シグナルが安全でない関数の実行を中断し、かつ handler が安全でない関数を呼び出した場合、プログラムの挙動は未定義である。_Exit()
_exit()
abort()
accept()
access()
aio_error()
aio_return()
aio_suspend()
alarm()
bind()
cfgetispeed()
cfgetospeed()
cfsetispeed()
cfsetospeed()
chdir()
chmod()
chown()
clock_gettime()
close()
connect()
creat()
dup()
dup2()
execle()
execve()
fchmod()
fchown()
fcntl()
fdatasync()
fork()
fpathconf()
fstat()
fsync()
ftruncate()
getegid()
geteuid()
getgid()
getgroups()
getpeername()
getpgrp()
getpid()
getppid()
getsockname()
getsockopt()
getuid()
kill()
link()
listen()
lseek()
lstat()
mkdir()
mkfifo()
open()
pathconf()
pause()
pipe()
poll()
posix_trace_event()
pselect()
raise()
read()
readlink()
recv()
recvfrom()
recvmsg()
rename()
rmdir()
select()
sem_post()
send()
sendmsg()
sendto()
setgid()
setpgid()
setsid()
setsockopt()
setuid()
shutdown()
sigaction()
sigaddset()
sigdelset()
sigemptyset()
sigfillset()
sigismember()
signal()
sigpause()
sigpending()
sigprocmask()
sigqueue()
sigset()
sigsuspend()
sleep()
sockatmark()
socket()
socketpair()
stat()
symlink()
sysconf()
tcdrain()
tcflow()
tcflush()
tcgetattr()
tcgetpgrp()
tcsendbreak()
tcsetattr()
tcsetpgrp()
time()
timer_getoverrun()
timer_gettime()
timer_settime()
times()
umask()
uname()
unlink()
utime()
wait()
waitpid()
write()
POSIX.1-2008 では、上記のリストのうち fpathconf(), pathconf(), sysconf() が削除され、以下の関数が追加された。
execl()
execv()
faccessat()
fchmodat()
fchownat()
fexecve()
fstatat()
futimens()
linkat()
mkdirat()
mkfifoat()
mknod()
mknodat()
openat()
readlinkat()
renameat()
symlinkat()
unlinkat()
utimensat()
utimes()
シグナルハンドラによるシステムコールやライブラリ関数への割り込み
システムコールやライブラリが停止 (block) している間にシグナルハンドラが起動されると、以下のどちらかとなる。- *
- シグナルが返った後、呼び出しは自動的に再スタートされる。
- *
- 呼び出しはエラー EINTR で失敗する。
これらの二つの挙動のうちどちらが起こるかは、インターフェイスにより依存し、シグナルハンドラが SA_RESTART フラグ ( sigaction(2) 参照) を使って設定されていたかにも依存する。詳細は UNIX システムによって異なる。 Linux における詳細を以下で説明する。
以下のインターフェイスのいずれかの呼び出しが停止している間にシグナルハンドラにより割り込まれた場合、 SA_RESTART フラグが使用されていれば、シグナルハンドラが返った後にその呼び出しは自動的に再スタートされることになる。それ以外の場合は、その呼び出しはエラー EINTR で失敗することになる。
- *
- read(2), readv(2), write(2), writev(2), ioctl(2) の「遅い (slow)」デバイスに対する呼び出し。ここでいう「遅い」デバイスとは、I/O 呼び出しが無期限に停止 (block) する可能性のあるデバイスのことで、例としては端末、パイプ、ソケットがある (この定義では、ディスクは遅いデバイスではない)。遅いデバイスに対する I/O 呼び出しが、シグナルハンドラにより割り込まれた時点までに何らかのデータをすでに転送していれば、呼び出しは成功ステータス (通常は、転送されたバイト数) を返すことだろう。
- *
- 停止 (block) する可能性のある open(2) (例えば、FIFO のオープン時; fifo(7) 参照)。
- *
- wait(2), wait3(2), wait4(2), waitid(2), waitpid(2).
- *
- ソケットインターフェイス: accept(2), connect(2), recv(2), recvfrom(2), recvmsg(2), send(2), sendto(2), sendmsg(2). 但し、ソケットにタイムアウトが設定されていない場合 (下記参照)。
- *
- ファイルロック用インターフェイス: flock(2), fcntl(2) F_SETLKW.
- *
- POSIX メッセージキューインターフェイス: mq_receive(3), mq_timedreceive(3), mq_send(3), mq_timedsend(3).
- *
- futex(2) FUTEX_WAIT (Linux 2.6.22 以降;それ以前は常に EINTR で失敗していた)。
- *
- POSIX セマフォインターフェイス: sem_wait(3), sem_timedwait(3) (Linux 2.6.22 以降;それ以前は常に EINTR で失敗していた)。
以下のインターフェイスは、 SA_RESTART を使っているどうかに関わらず、シグナルハンドラにより割り込まれた後、再スタートすることは決してない。これらは、シグナルハンドラにより割り込まれると、常にエラー EINTR で失敗する。
- *
- setsockopt(2) を使ってタイムアウトが設定されているソケットインターフェース: accept(2), recv(2), recvfrom(2), recvmsg(2) で受信タイムアウト ( SO_RCVTIMEO) が設定されている場合と、 connect(2), send(2), sendto(2), sendmsg(2) で送信タイムアウト ( SO_SNDTIMEO) が設定されている場合。
- *
- シグナル待ちに使われるインターフェイス: pause(2), sigsuspend(2), sigtimedwait(2), sigwaitinfo(2).
- *
- ファイルディスクリプタ多重インターフェイス: epoll_wait(2), epoll_pwait(2), poll(2), ppoll(2), select(2), pselect(2).
- *
- System V IPC インターフェイス: msgrcv(2), msgsnd(2), semop(2), semtimedop(2).
- *
- スリープ用のインターフェイス: clock_nanosleep(2), nanosleep(2), usleep(3).
- *
- inotify(7) ファイルディスクリプタからの read(2).
- *
- io_getevents(2).
sleep(3) 関数も、ハンドラにより割り込まれた場合、決して再スタートされることはない。しかし、成功となり、残っている停止時間を返す。
一時停止シグナルによるシステムコールやライブラリ関数への割り込み
Linux では、シグナルハンドラが設定されていない場合でも、いくつかのブロッキング型のインターフェイスは、プロセスが一時停止 (stop) シグナルの一つにより停止され、 SIGCONT により再開された後に、エラー EINTR で失敗する可能性がある。この挙動は POSIX.1 で認められておらず、他のシステムでは起こらない。- *
- setsockopt(2) を使ってタイムアウトが設定されているソケットインターフェース: accept(2), recv(2), recvfrom(2), recvmsg(2) で受信タイムアウト ( SO_RCVTIMEO) が設定されている場合と、 connect(2), send(2), sendto(2), sendmsg(2) で送信タイムアウト ( SO_SNDTIMEO) が設定されている場合。
- *
- epoll_wait(2), epoll_pwait(2).
- *
- semop(2), semtimedop(2).
- *
- sigtimedwait(2), sigwaitinfo(2).
- *
- inotify(7) ファイルディスクリプタからの read(2).
- *
- Linux 2.6.21 以前: futex(2) FUTEX_WAIT, sem_timedwait(3), sem_wait(3).
- *
- Linux 2.6.8 以前: msgrcv(2), msgsnd(2).
- *
- Linux 2.4 以前: nanosleep(2).
準拠
POSIX.1 (注記した内容以外)。関連項目
kill(1), getrlimit(2), kill(2), killpg(2), rt_sigqueueinfo(2), setitimer(2), setrlimit(2), sgetmask(2), sigaction(2), sigaltstack(2), signal(2), signalfd(2), sigpending(2), sigprocmask(2), sigsuspend(2), sigwaitinfo(2), abort(3), bsd_signal(3), longjmp(3), raise(3), pthread_sigqueue(3), sigqueue(3), sigset(3), sigsetops(3), sigvec(3), sigwait(3), strsignal(3), sysv_signal(3), core(5), proc(5), pthreads(7), sigevent(7)この文書について
この man ページは Linux man-pages プロジェクトのリリース 3.51 の一部である。プロジェクトの説明とバグ報告に関する情報は http://www.kernel.org/doc/man-pages/ に書かれている。2012-05-01 | Linux |