ファイヤープロジェクト
シグナルをキャッチしてみる
2003-07-20T15:13+09:00   matsu
まずは基本.BASHでいうとtrapになるだろうか.
シグナルと言って思い出すのはkillとか端末からのC-cだろうか.killはプロセスにシグナルを送るコマンドで(関数もある),C-cはシェルがシグナルを生成してプロセスに送る.とにかく我々は普段シグナルを送信しまくっている.で,シグナルというのは結局なんなのかというと,(割り込み)イベントである(と思う).GUIではイベント駆動とか言って,ボタンがクリックされたらこれを実行するなどと指定するが,シグナルも同様で,このシグナルをキャッチしたらあれを実行するという風に指定しておく.そして実際にプロセスがシグナルをキャッチしたらあれを実行する.この「あれ」はシグナルハンドラと呼ばれるなんらかの関数である.
シグナルはイベントで,いろいろなイベントがあるハズだ.これは
man 7 signal
で参照できる.これらの中にはキャッチできないものや無視できないものなどがある.
シグナルをキャッチするもっとも簡単なサンプルを以下に示す.
サンプルでやっているのは,シグナルハンドラをデフォルトとは違ったものに設定する,という処理である.で,そのシグナルハンドラの設定は関数signalで行なう.その関数ヘッダを以下に示す.
void (*signal(int sig,void (*func)(int)))(int);
かなり変態的である.カーニハンとリッチーによるプログラミング言語C(ISBN 4-320-02692-6)を参考に翻訳すると
signal is a function(int, function(int) returning pointer to void) returning pointer to function(int) returning void.
となるだろうか.これを読みやすくすると,man signalにあるように
typedef void (*sighandler_t)(int);

sighandler_t signal(int signum, sighandler_t sighandler);
となる.一つtypedefするだけでかなり読みやすくなった.で,シグナルハンドラに特別なものとして以下のものがある.
SIG_IGN
シグナルを無視する
SIG_DFN
デフォルトの動作
サンプルではSIG_DFNを使用している.また,signal関数の返り値は成功時は以前のシグナルハンドラで,失敗時はSIG_ERRである.そしてSIG_ERROが返ったときはerrnoに正の値が設定される.UNIXオリジナルのsignalは一回シグナルをキャッチするとシグナルハンドラはデフォルトになるらしいが,私のシステムではそうはならなかった.
matsu(C)
Since 2002
Mail to matsu