シグナル (ソフトウェア)

シグナル (ソフトウェア)の最新ニュースをまとめて検索!

シグナルsignal)とは、UNIXオペレーティングシステムにおいてプロセス間で非同期イベントの発生を伝える機構。

UNIX系およびPOSIX準拠のオペレーティングシステムでは、シグナルの種類と使用法が規定されている。kill()システムコールはシグナルを送信するのに使われ、signal()sigaction()システムコールは「シグナルハンドラ」を設定するのに使われる。シグナルハンドラとは、シグナルを受信してそのシグナルに対応した処理をする関数である。

[編集] 発生条件

以下のような条件によりシグナルが発生する。

  • ユーザーが端末のキーを押下したとき、端末がシグナルを発生する。例えば、ユーザーが CTRL + C キーでプログラムを中断しようとしたときなど。
  • ハードウェア例外によってもシグナルが発生する。ゼロ除算不正メモリ参照など。経験の浅いプログラマはポインタに不正アドレスを入れてしまい、SIGSEGV(セグメンテーション違反シグナル)を発生させることが多い。
  • プロセスは kill()システムコールを使って自分自身にシグナルを送ることができる。
  • カーネルは何かが起きたことを知らせるためにプロセスにシグナルを送信することがある。例えば、SIGPIPE は読み手がクローズしたパイプに書き手のプロセスが書き込もうとしたときに発生する。

シグナルは処理中のシステムコールを中断することがあり、アプリケーションは非透過的な再実行をしなければならない。つまり、実行中のシステムコールはEINTRというエラーを返し、要求した処理はシグナル受信によって中断されて結果を得られていないことを示す。そのため、処理を続行するには再度同じシステムコールを実行しなければならない。

[編集] 個々のシグナル

Single UNIX Specification では、以下のシグナルを <signal.h> で定義すべきものとして指定している。

注:アスタリスク付の項目は、X/Open System Interfaces (XSI) による拡張を示す。(SUS)とある部分はSUS[1]にある表現の引用(を和訳したもの)。

SIGABRT - プロセスが中断された
abort()をプロセス自身が実行することによって発生する。ハンドラによるキャッチ可能。ブロック不可。シグナルハンドラから戻るとプロセスは終了させられる。何らかの不正な状況に陥ったが通常の処理の流れでは終了前のクリーンアップ処理ができないときに使用。
SIGALRM - alarm() によるシグナル
alarm()システムコールで、設定した実時間タイマーがタイムアウトしたことを知らせる。
SIGBUS - 「未定義メモリ領域へのアクセス」(SUS)によるバスエラー
以下のような不正なメモリ操作により発生。ハンドラでキャッチできるが、ハンドラから戻った後の動作はシステムに依存する(通常プロセスの終了)。
  • アドレス境界不正:CPUはデータのサイズによって配置可能なアドレスに制限があることが多い。例えば32bit整数を4バイト境界(4で割り切れるアドレス)以外に置こうとしたなど。
  • 存在しない物理アドレス:ページフォールトに似ているが物理アドレスに関して発生。
  • オブジェクト固有エラー:例えば、mmapでマッピングされたファイルが切り捨てられたために仮想アドレスに対応する実体が存在しなくなった場合など。
SIGCHLD - 子プロセスが終了、停止(または再開)した
子プロセスの状態変化に応じて発生。親プロセスは無視することもできる。
SIGCONT - 停止していれば再開
SIGSTOPによって停止していれば実行再開する。それ以外は無視される。プロセスグループを参照。
SIGFPE - 浮動小数点例外 -- 「不正な算術操作」(SUS)
浮動小数点演算ゼロ除算やオーバーフローなどが発生したときに発生。Signaling NaNが発生したときも同様。また、整数のオーバーフローなどでも発生する。ハンドラでキャッチ可能だが、適切に処理しないとプロセスがハングアップ(無限ループ)に陥る可能性がある。(ここでいう適切な処理とは、シグナルハンドラが受け取る例外発生時のレジスタの内容を書き換えて例外が発生しないようにすることであり、例外発生箇所のコードを解析してどのレジスタが使われていたのかを調べたり、内容を書き換えることで計算結果が不正にならないか判断したりといった非常に高度な対応が必要とされる。また、Signaling NaN 以外では処理続行はほぼ不可能)
SIGHUP - ハングアップ
本来は端末の回線が切れたときに発生。現在では仮想端末をクローズしたときにその端末から起動されたプロセスグループに送られる。シェルの nohup 機能を使えばバックグラウンドのプロセスがSIGHUPを受け付けないようにできる。デフォルトではSIGHUPを受信したプロセスは強制終了させられる。
SIGILL - 不正命令
通常、命令でないメモリ領域にジャンプしたときに発生(コールスタックのリターンアドレスが破壊されたときなど)。他に特権レベルが高くないと実行できない命令を実行しようとしたときなどにも発生する。
SIGINT - 割り込み
端末から割り込みキー(通常 CTRL + C)を押下したときに発生。
SIGKILL - 強制終了(kill)
killコマンドなどで明示的に発生させる。キャッチしたり無視したりできず、受信プロセスは強制終了させられる。ゾンビプロセスは既に終了しているのでSIGKILLを受けても消滅しない。スリープ中プロセスはスリープ解除されたときにSIGKILLを受け付ける。initはSIGKILLを無視できる。
SIGPIPE - 読み手のいないパイプへの書き込み
デフォルトでは受信プロセスは終了させられる。
SIGQUIT - 終了
通常、端末からの終了キー(CTRL + \)で発生。
SIGSEGV - セグメンテーション違反ページフォールト
ページフォールトのうち不正なメモリアクセスによるものの場合に発生。しかし、例えばヒープ領域の拡張をSIGSEGV発生を受けてオンデマンドで行うライブラリなどもある。
SIGSTOP - 実行中断
プロセスグループの実行中断のためのシグナル。キャッチも無視もできない。SIGCONT シグナルで実行再開する。
SIGTERM - 強制終了
killコマンドがデフォルトで発生するシグナル。しかし、このシグナルをキャッチしたり無視したりすることも可能。
SIGTSTP - 端末からの中断シグナル
フォアグラウンドのプロセスグループを実行中断させる(通常、CTRL + Z 押下)。
SIGTTIN - バックグラウンドプロセスが端末から読もうとした
バックグラウンドのプロセスグループがユーザー入力待ちとなって停止。シェルの機能を使ってフォアグラウンドにすることで入力が可能。
SIGTTOU - バックグラウンドプロセスが端末に書き込もうとした
バックグラウンドのプロセスグループが端末への表示待ちとなって停止。シェルの機能を使ってフォアグラウンドにすることで表示可能。
SIGUSR1 - ユーザー定義シグナル 1
POSIXでは未定義。Linuxではスレッド間同期に使用。ddコマンドが受信すると操作の状況が表示される。
SIGUSR2 - ユーザー定義シグナル 2
POSIXでは未定義。Linuxではスレッド間同期に使用。
*SIGPOLL - poll可能イベント
ファイル記述子に対してfcntl()システムコールでシグナル発生を指示すると、ポール可能イベントに伴ってSIGPOLLが発生する。一般に通信ポートに対応するファイル識別子に使用し、完全な非同期I/Oを実現する。ただし、コードが複雑化することから、最近では専用の非同期I/Oシステムコールを使用することが推奨されている。
*SIGPROF - プロファイリングタイマーがタイムアウト
プロファイラで使用。このときのタイマーはプロセスの全実行時間に対応する(CPUモードに関わらず計時する)。
*SIGSYS - 不正 システムコール
一般にシステムコールの番号や引数が不正だったときは単にエラーを返すことで済むので、このシグナルは滅多に使われない。
*SIGTRAP - トレース/ブレークポイントによるトラップ
何らかのデバッグ機能で使用される(アーキテクチャによって異なる)。
SIGURG - ソケット上に緊急データがある
非同期I/O機能で使用。
*SIGVTALRM - 仮想時間をカウントするタイマによるシグナル -- 「仮想タイマのタイムアウト」(SUS)
プロファイラなどで使用。このときのタイマーはプロセスのユーザーモードでの実行時間を計時するもの。SIGPROFと組み合わせると、プロセスのカーネルモードでの実行時間がわかる。
*SIGXCPU - CPU時間制限を越えた
プロセス実行時間(スリープしていた時間やスケジューリング待ち時間は除く)がある値を超えると発生。
*SIGXFSZ - ファイルサイズ制限を越えた
ファイルサイズがファイルシステム(あるいはオペレーティングシステム)の制限を越えようとしたとき、それを引き起こしたプロセスに送信される。

[編集] 外部リンク

最終更新 2009年11月24日 (火) 11:39 (日時は個人設定で未設定ならばUTC)。
【シグナル (ソフトウェア)】変更履歴

ご利用上の注意