日々精進

aikoと旅行とプログラミング

イベントの発生を伝えるsignal関数メモ

今回はイベントの発生を伝えるシグナル(割り込み)を発生させる関数signalについてのメモ。POSIXでは非推奨となっているが、諸事情によりsignal関数について明記することにする。

書式

#include <signal.h>

typedef void (*sighandler_t)(int);

sighandler_t signal(int signum, sighandler_t sighandler);  

概要

signal関数は移植性が低いため、この関数の使用は避けてsigaction関数を利用することを推奨する。
signal関数はsignumに指定されたシグナルの処理方法をhandlerに設定する機能を持つ。第一引数にはシグナルの番号、第二引数にはSIG_DFL(デフォルトの処理)・SIG_IGN(シグナルを無視する)・ユーザー定義関数のアドレスを設定する。SIGKILLとSIGSTOPに関しては補足することができず、無視も不可能である。 代表的なシグナルは以下の通り。

名前 意味
SIGHUP ターミナルのハングアップ検出
SIGINT キーボードからの割り込み(Ctrl-C)
SIGQUIT キーボードによる中止
SIGABRT アボートシグナル
SIGKILL KILLシグナル
SIGALRM タイマーシグナルの感知
SIGTSTP 端末から入力された一時停止(Ctrl-Z)

返り値

今まで設定していたハンドラ(SIG_DFL, SIG_IGN, 関数のアドレス)が返る。エラーの場合SIG_ERRを返し、帯域変数errnoにエラー情報が格納される。

実装例

SIGINT(Ctrl-C)が5回押されたら終了するプログラム。

#include <stdio.h>
#include <signal.h>
#include <unistd.h>

static int count = 0;

void handler(int signal){
  printf("Ctrl-C executed\n");
  count++;
}

int main(){
  
  if(signal(SIGINT, handler) == SIG_ERR){
    return 1;
  }
  
  while(count < 5){
    sleep(2);
  }
  
  return 0;
}

sleep関数はシグナルが発生したら残りの秒数を返り値にして処理が復活するため、SIGINTが5回発生すれば10秒経たずとも終了する。