シグナル (Unix)

シグナル（）とは、Unix系（POSIX標準に類似の）オペレーティングシステム (OS) における、限定的なプロセス間通信の形式を使って、プロセスに対し、非同期で、イベントの発生を伝える機構である。シグナルが送信された際、OSは宛先プロセスの正常な処理の流れに割り込む。どんな不可分でない処理の間でも割り込むことができる。受信プロセスが以前にシグナルハンドラを登録しておけば、シグナル受信時にそのルーチンが実行される。さもなくば、デフォルトのシグナル処理が行われる。（同様なものは他のTSSなどでも開発されてはいるが、UNIXのシグナルは）1970年ごろベル研究所でUNIXに実装された。後にPOSIXである程度は標準化されているが、標準化が諦められているような振舞などもいくつかあり、特に他の幾つかの要素（fork等）とマルチスレッドとシグナルが絡むと実装毎の対処にプログラミングが大変になることがある。プロセスはI/O待ちなど、カーネルの内部で処理がブロックしている場合などで割り込み不可状態になることがあり、その場合は如何なるシグナルを送っても無効になる。
シグナル送信.
以下のような操作によりシグナルが送信される。
シグナル処理.
codice_2やcodice_3システムコールは「シグナルハンドラ」を設定するのに使われる。シグナルハンドラが設定されていないシグナルの場合、デフォルトのハンドラが使われる。さもなくば、シグナルは捉えられ、シグナルハンドラが呼び出される。プロセスはハンドラを設定しなくとも2種類のデフォルト動作を指定できる。シグナルを無視するか（SIG_IGN）、デフォルトのハンドラを使うか（SIG_DFL）である。SIGKILLとSIGSTOPは、捉えることもハンドラで処理することもできないシグナルである。
問題.
ハンドラによるシグナル処理は競合状態に弱い。シグナルは非同期イベントなので、あるシグナルをハンドラで処理中に別のシグナル（同じ種類ということもある）がそのプロセスに送られてくることがある。このような状態を防ぐため、codice_3 を使ってシグナル配送のブロック/アンブロックが可能である。
シグナルは処理中のシステムコールを中断することがあり、アプリケーションは非透過的な再実行をしなければならない。つまり、実行中のシステムコールはEINTRというエラーを返し、要求した処理はシグナル受信によって中断されて結果を得られていないことを示す。そのため、処理を続行するには再度同じシステムコールを実行しなければならない。
シグナルハンドラは通常の処理に割り込んで呼び出されるので、不要な副作用を起こさないように注意が必要である。例えば、大域変数である errno を変化させてはならない。シグナルマスクを変化させてはならない。シグナル処理方法を変化させてはならない。その他のプロセスの大域的な属性を変化させてはならない。malloc、printfといった非同期シグナル安全(async‐signal‐safe)でない関数を使うのも安全ではない。
ハードウェア例外との関係.
プロセスの実行によってハードウェア例外が発生することがある。例えば、プロセスがゼロ除算を行おうとしたときや、TLBミスを引き起こしたときなどである。Unix系OSでは、ハードウェア例外が発生するとコンテキストを自動的に切り替えてカーネルの例外ハンドラを実行開始する。ページフォールトなどの一部の例外の場合、カーネルはそのイベントを処理するのに十分な情報を持っているので、プロセスの実行を再開させることができる。しかし他の例外ではカーネルはうまく処理できず、代わりに例外を発生させた処理を行っていたプロセスに例外処理を委任しなければならない。シグナルはこの委任のための機構としても機能し、カーネルからプロセスに対してその例外に対応したシグナルを送信する。例えば、x86 CPU でゼロ除算を行おうとした場合 "divide error" 例外が発生し、カーネルがそのプロセスにSIGFPEというシグナルを送信する。同様に、あるプロセスが自身の仮想アドレス空間の範囲外のメモリアドレスにアクセスしようとした場合、カーネルはSIGSEGVシグナルを送信する。ハードウェア例外の種類はCPUのアーキテクチャによって異なるので、ある例外が発生したときどういうシグナルが送信されるかは厳密にはCPUアーキテクチャやカーネルの実装に依存する。
個々のシグナル.
Single UNIX Specification では、以下のシグナルを <signal.h> で定義すべきものとして指定している。
シグナル受信時のデフォルト動作は以下のような処理がある:
下記表のシグナル番号は Linux x86 の場合であり、他のOS・他のCPUでは異なる。Linux ARM もシグナル番号は同じ。
注：アスタリスク付の項目は、X/Open System Interfaces (XSI) による拡張を示す。(SUS) とある部分はSUSにある表現の引用（を和訳したもの）。
上述以外に、プロセスは擬似シグナル（番号0）を送信することもできる。これは実際にはシグナルを送信せずにシグナル送信時のエラーチェックをし、例えば宛先プロセスが存在するかどうかをチェックするのに便利である。