IPC: シグナル

シグナルは、ソフトウェアの割り込み機構で非同期処理の実装に利用されます。

SYNOPSIS

#include <signal.h>
 
void (*signal (int sig, void (*disp)(int)))(int);
int sigaction(int sig, const struct sigaction  *act,  struct sigaction *oact);

DESCRIPTION

シグナルは、ソフトウェアの割り込み機構で非同期処理の実装に利用されます。あるプロセスがシグナルを受信すると、そのプロセスが現在実行中の処理を一時中断し、そのシグナルに対応したシグナルハンドラを実行します。シグナルハンドラの処理が終了すると、中断していた処理を再開します。

シグナルハンドラとは、プロセスがシグナルを受信したときに実行する関数のことです。この関数の中で、生じたシグナルに対応する処理を記述します。

シグナルの発生は、プログラムや子プロセスなどから発生することが考えられ、また、kill コマンドにより発生させることが出来ます。kill コマンドにシグナルのタイプを指定し、シグナルを送りたいプロセスのプロセスID を指定します。

    # ps -ef | grep sample
        shin  1149  1147  0 18:43:56 ?        0:03 sample
    # kill -9 1149
    # <Enter>
    [1]+  killed                  sample
    # 

シグナルのタイプは以下の表のとおりです。(Solaris の場合)

シグナル名 Value 詳細
SIGHUP 1 Hangup
SIGINT 2 Interrupt
SIGQUIT 3 Quit
SIGILL 4 Illegal Instruction
SIGTRAP 5 Trace or Breakpoint Trap
SIGABRT 6 Abort
SIGEMT 7 Emulation Trap
SIGFPE 8 Arithmetic Exception
SIGKILL 9 Killed
SIGBUS 10 Bus Error
SIGSEGV 11 Segmentation Fault
SIGSYS 12 Bad System Call
SIGPIPE 13 Broken Pipe
SIGALRM 14 Alarm Clock
SIGTERM 15 Terminated
SIGUSR1 16 User Signal 1
SIGUSR2 17 User Signal 2
SIGCHLD 18 Child Status Changed
SIGPWR 19 Power Fail or Restart
SIGWINCH 20 Window Size Change
SIGURG 21 Urgent Socket Condition
SIGPOLL 22 Pollable Event
SIGSTOP 23 Stopped (signal)
SIGTSTP 24 Stopped (user)
SIGCONT 25 Continued
SIGTTIN 26 Stopped (tty input)
SIGTTOU 27 Stopped (tty output)
SIGVTALRM 28 Virtual Timer Expired
SIGPROF 29 Profiling Timer Expired
SIGXCPU 30 CPU time limit exceeded
SIGXFSZ 31 File size limit exceeded
SIGWAITING 32 Concurrency signal reserved by threads library
SIGLWP 33 Inter-LWP signal reserved by threads library
SIGFREEZE 34 Check point Freeze
SIGTHAW 35 Check point Thaw
SIGCANCEL 36 Cancellation signal reserved by threads library
SIGXRES 37 Resource control exceeded
SIGRTMIN * First real time signal
(SIGRTMIN+1) * Second real time signal
...
(SIGRTMAX-1) * Second-to-last real time signal
SIGRTMAX * Last real time signal

SAMPLE

プログラムの処理のはじめで、どのシグナルを拾って処理するか signal()関数を使って定義しています。また、シグナルハンドラとなる関数を最後に定義しています。

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <signal.h>
 
void sigint_handler(int sig);
 
int main(void)
{
    char s[200];
 
    if (signal(SIGINT, sigint_handler) == SIG_ERR) {
        perror("signal");
        exit(1);
    }
 
    printf("Enter a string: ");
 
    if (gets(s) == NULL) {
        perror("gets");
    } else {
        printf("You entered - \"%s\"\n", s);
    }
 
    return 0;
}
 
void sigint_handler(int sig)
{
    printf("Got a signal -> SIGINT\n");
}

これをコンパイルし実行すると以下のようになります。はじめは普通にプログラムを実行しています。2回目は、途中で Ctrl-C をタイプしてプログラムを中断しています。Ctrl-C をタイプした時点で、シグナルハンドラが呼び出されていることが確認できます。

    # gcc signal_sample.c -o signal_sample
    # ./signal_sample
    Enter a string: hello
    You entered - "hello"
    # 
    # ./signal_sample
    Enter a string: ^CGot a signal -> SIGINT
    gets: Interrupted system call
    # 

SEE ALSO

signal(3), sigaction(2), kill(2)

 

戻る