その時々

その時々で違うんです。特に決まっていないんです。

シグナル処理

ちょっと気になったのでシグナル処理について調査してみました。

シグナルとはプロセス間で連絡を取り合う手段です。
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について