シグナルによるプロセスの制御の仕組み
「シグナル」とは、割り込みによってプロセスに特定の動作をするように通知するための仕組みです。シグナルを受信したプロセスは、シグナルに応じた処理を実行します。シグナルを受信したときに実行する処理は、プログラムの中に関数として登録しておくことができます。この関数のことを「シグナルハンドラ」と呼びます。受信したシグナルに対応するシグナルハンドラがプロセスに登録されていない場合には、デフォルトのシグナルハンドラが実行されます。
プロセスの間でシグナルを送受信したときの動作イメージは次図のとおりです。図では、プロセス終了を意味するSIGTERMシグナルを送受信したときの様子を表しています。
シグナルにはたくさんの種類があります。主なものは次表のとおりです。送信するシグナルは「シグナル名」で指定しますが、実際に送信されるのは「シグナル番号」です。シグナルを受信するプロセスも、どのシグナルが届いたのかはシグナル番号で判別します。「動作」はデフォルトのハンドラが行う処理です。「表示メッセージ」は、デフォルトのハンドラが実行されたときに表示されるメッセージです。
| シグナル番号 | シグナル名 | 動作 | 表示メッセージ | 説明 | 試験での重要度 |
|---|---|---|---|---|---|
| 1 | SIGHUP | 終了 | Hangup | 制御ターミナルのハングアップまたは制御プロセスの消滅 | ★★★ |
| 2 | SIGINT | 終了 | (表示なし) | キーボード操作による割り込み(Ctrl+c) | ★★★ |
| 3 | SIGQUIT | 終了+コアダンプ | Quit (core dumped) | キーボード操作による終了(Ctrl+\) | - |
| 9 | SIGKILL | 強制終了 | Killed | 強制終了 | ★★★ |
| 11 | SIGSEGV | 終了+コアダンプ | Segmentation fault (core dumped) | 不正なメモリ参照 | - |
| 15 | SIGTERM | 終了 | Terminated | 終了 | ★★★ |
| 18 | SIGCONT | 実行再開 | (表示なし) | 一時停止プロセスの再開 | - |
| 19 | SIGSTOP | 強制一時停止 | (表示なし) | 強制一時停止 | - |
| 20 | SIGTSTP | 一時停止 | (表示なし) | キーボード操作による一時停止(Ctrl+z) | - |
なお、SIGCONT、SIGSTOP、SIGTSTPの各シグナルは、CPUアーキテクチャによってシグナル番号が異なります。この表はx86アーキテクチャの場合の番号です。
シグナルの送信
シグナルは、kill、killall、pkillコマンドで送信できます。コマンドには送信するシグナルを指定しますが、指定を省略した場合にはSIGTERMシグナルが送信されます。また、指定するシグナル名では先頭の「SIG」を省略できます。例えば、SIGHUPシグナルは「HUP」、SIGINTシグナルは「INT」と書くことができます。
フォアグラウンドプロセスに対しては、上記の表のとおり、Ctrl+c、Ctrl+\、Ctrl+zの各キーボード操作によりシグナルを送信できます。
シグナルの受信
本稿の冒頭でも述べたとおり、シグナルを受信したプロセスに該当するシグナルハンドラが登録されていない場合には、デフォルトのシグナルハンドラが実行されます。ハンドラ名は「SIG_DFL」です。
シグナルハンドラの登録には、signal()とsigacton()というシステムコール(カーネルの処理を呼び出すC言語の関数)が利用できます。それぞれ次のように使います。
-
signal()は引数にシグナルとハンドラを指定して実行します(後述のプログラム例2を参照) -
sigacton()は引数にシグナルと、シグナルハンドラを要素に含むsigaction構造体を指定して実行します(後述のhttpdとnamedの例を参照) -
signal()の動作はシステムによって異なるため、移植性が必要な場合はsigacton()を使うことが推奨されています。
プログラムの中で独自にシグナルハンドラを登録することにより、上記の表とは異なる機能を持たせることもできます。ただし、SIGKILLは強制的に終了させるための、SIGSTOPは強制的に一時停止させるための特別なシグナルであり、プロセスはこれら2つのシグナルだけは捕捉できないため、プロセス自身の中で処理をすることができません。
プロセスが送信したシグナルは、カーネルを経由して送信先のプロセスに配信されます。ただし、SIGKILLとSIGSTOPは送信先プロセスに配信されることなく、カーネルによって強制的な終了あるいは一時停止の処理が行われます。

