ユユユユユ

webエンジニアです

シグナルを送ることで他のプロセスに割り込みをおこなう

シグナルとは、小さなメッセージのようなもので、何らかのイベントがシステム内で発生したことをプロセスに通知するものである1

 ハードウェアレベルで例外が起こるとする。たとえばあるプロセスがゼロ除算エラーを発生させるとする。通常はカーネルがこの例外を補足してハンドルするため、個々のユーザープロセスは個別にハンドラを定義しないし、そうする必要もない。要するに、ユーザープロセスにはこの例外は見えない。

 この種の例外の発生をイベントとして通知して、ユーザープロセスが例外を検出することができるようにするのがシグナルである。ゼロ除算エラーの場合、カーネルは SIGFPE (8) をユーザープロセスに送る。

 シグナルを受信したユーザープロセスは、シグナルを無視したり、実行を終了したり、ユーザー定義のハンドラを実行してシグナルをキャッチすることができる。なにもしない場合、シグナルごとに定義されたデフォルトアクションが実行される。たとえば SIGKILL (9) のデフォルトアクションはプロセスを終了させることである。

 シグナルは、低レベルの例外を検出したカーネルからユーザープロセスに送信されることもあれば、ユーザープロセスからユーザープロセスに送信されることもある。つまり、システムイベントの通知がシグナルとして抽象化された結果として、ユーザーが任意のシグナルを発行して、あたかもあるシステムイベントが発生したかのようにプロセスを制御することも可能にされたわけである。

 シグナルとそのデフォルトアクションのリストは、さまざまなところに掲示されている。ひとまず wikipedia のテーブルをみるのが無難とおもう。

https://en.wikipedia.org/wiki/Signal_(IPC)#Default_action

 たとえば kill コマンドをこうやって使うことは、駆け出しエンジニアのころに意味も知らないままに覚えて、以来無批判に使っている。

kill -9 pid

 引数にあたる -9 は SIGKILL に割り当てられた数字であり、これはプログラムの強制終了を指示するシグナルである。こう書いても同じことを意味することになる。

kill -s KILL pid

 引数 pid に負数を渡すと、プロセスグループに対するシグナル送信とすることができる。手元のマシンの kill のマニュアルにはその記載はなく、試してみてもいないのでわからない。とはいえ使う機会があるかもしれないので知識としてのみ覚えておく。

 unicorn の起動スクリプトに埋め込んでいた HUP や USR2 のシグナルの意味もいまならわかる。

 tablexi/capistrano3-unicorn は QUIT, HUP, USR2, TTIN, TTOU といったシグナルを送信するタスクを定義している2。これらのシグナル群について、 unicorn がシグナルハンドラを提供している3。この仕様に沿ってシグナルを送信することで、プロセスをたとえばグレースフルリスタートさせるような制御をおこなうことができるわけである。