シグナル処理
ちょっと気になったのでシグナル処理について調査してみました。
シグナルとはプロセス間で連絡を取り合う手段です。
killコマンドでシグナルをプロセスにたいして送信できます。
killのデフォルトはTERMです。
Linuxにおけるmanページに記載されているオプションをいくつか見てみます。
シグナル | 番号 | 説明 |
HUP | 1 | hang up の略で、終了のあと再起動します |
INT | 2 | interrupt(中断)の意味を持つシグナルで、プロセスを中断させる。 |
QUIT | 3 | 終了。通常、端末からの終了キー(CTRL + \)で発生。 |
ILL | 4 | 不正命令。命令でないメモリ領域にジャンプしたときに発生。 |
TRAP | 5 | トレース/ブレイクポイント。ブレイクポイントを用いてのデバッグ作業や、システムコールのトレースを行なう際に用いられる。 |
ABRT | 6 | 異常終了 |
FPE | 8 | 浮動小数点例外 |
KILL | 9 | 強制終了。無視できない。 |
SEGV | 11 | セグメンテーション違反(ページフォールト) |
PIPE | 13 | 読み手のいないパイプへの書き込み |
ALRM | 14 | alarm()システムコールで、設定した実時間タイマーがタイムアウトしたことを知らせる。 |
TERM | 15 | 強制終了。しかし、このシグナルをキャッチしたり無視したりすることも可能。 |
シグナルを使ったサンプルプログラム
#include <signal.h> #include <stdio.h> #include <stdlib.h> void sigcatch(int); int main(){ if (SIG_ERR == signal(SIGHUP, sigcatch)){ printf("failed to set signal handler\n"); exit(0); } while(1){ sleep(1); } return 0; } void sigcatch(int sig){ printf("catch signal %d\n", sig); exit(1); }
実行例
端末1
$ ./sigtest
端末2
$ ps -ef | grep sigtest hogehoge 25392 3282 0 08:06 pts/4 00:00:00 ./sigtest hogehoge 25414 25393 0 08:07 pts/2 00:00:00 grep --color=auto sigtest $ kill -HUP 25392
端末1
catch signal 1
SIGHUPが期待通り送られていることが分ります。
SIGTERMならどおでしょうか。
端末1
$ ./sigtest
端末2
$ ps -ef | grep sigtest hogehoge 25392 3282 0 08:06 pts/4 00:00:00 ./sigtest hogehoge 25414 25393 0 08:07 pts/2 00:00:00 grep --color=auto sigtest $ kill 25392
端末1
Terminated
Terminatedと表示されました。
終了コードを見てみましょう。
端末1
$ echo $? 0
0となっています。
failed to set signal handler
と表示されずに終了していますね。
しかしよく見てみますと
SIG_ERRだった場合に
failed to set signal handler
と表示するようになっているのです。
SIG_ERRとはmanを見てみますと
signalがエラーの場合にSIG_ERRを返すとなっています。
というわけで、
return 0 のほうへ抜けたのですね。
ちょっと改造してみます。
sigtest2.c
#include <signal.h> #include <stdio.h> #include <stdlib.h> void sigcatch(int); int main(){ if (SIG_ERR == signal(SIGINT, sigcatch)){ printf("failed to set signal handler\n"); exit(0); } while(1){ sleep(1); } return 0; } void sigcatch(int sig){ printf("catch signal %d\n", sig); exit(1); }
SIGHUPではなくSIGINTを設定してみました。
SIGINTはCtrl+Cでも送れます。
その確認です。
$ ./sigtest2
^Ccatch signal 2
期待通りです。
最後にSIGALRAMについてです。
#include <stdio.h> #include <signal.h> #include <stdlib.h> main() { int i; char buf[16]; extern void timeout(); signal(SIGALRM,timeout); alarm(5); printf("Input keyword : "); gets(buf); alarm(0); printf("end\n"); } void timeout(int sig) { printf("\nSIGALRM timeout\n"); signal(SIGALRM,timeout); }
5秒以内にキーワードを入力しないとtimeoutします。
シグナルは、このような感じで使用することが出来ます。
参考URL
C言語シグナルをキャッチする サンプルコード
kill and killall
UNIX/Linux入門 - Wikibooks
シグナル (ソフトウェア) - Wikipedia
SIGTRAP ‐ 通信用語の基礎知識
SIGALRAMについて