ソフトウェア割込みとシグナル

■ソフトウェア割込みとシグナル

普通の割込み(ハードウェアによる割込み)は、 オペレーティング・システムのカーネルで利用されています。

ソフトウェア割込みとは、本来はオペレーティング・システムのカーネルしか 使えない割込みの機能を、ソフトウェアにより実現して、 一般の利用者プログラム(プロセス)でも使えるようにしたものです。

UNIXでは、ソフトウェア割込みの機能は、 シグナル(signal) で実現しています。

シグナルとは、本来はプロセス間通信の一種で、 ある事象が起きたことを他のプロセスに知らせることです。 ここで伝わるのは、ある事象が起きたかどうかだけで、 引数などを付けることはできません。 UNIXでは、プロセス間でシグナルにより通信をする他に、 キーボードからシグナルを送ることもできます。

これは、ソフトウェア割込みとして、 プロセスひとつひとつに割込みボタンが付いているようなものです。 また、プログラムの中で例外(exception)が起きた時にも、 ハードウェアの割込みと同様に、ソフトウェア割込みが起きます。 これも、他のシグナルと同じように受け取ることができます。

UNIXのソフトウェア割込み(シグナル)を使うには、次のようなことが必要です。

割り込みハンドラが設定されていない時は、 プロセスはデフォルトの動作をします。
デフォルトには、次の3つがあります。 signal の種類は、signal(5) または signal(7) にあります。

ソフトウェア割り込みは、 1つのプログラムの中に制御の流れが1つしかないようなプログラムに有効な方法です。 最近のマルチスレッドのプログラムでは、シグナルの意味が不明確です。


----------------------------------------------------------------------
/*
        signal-int.c -- SIGINT を3回受け付けて終了するプログラム。
*/

#include <stdio.h>
#include <signal.h>
	
int sigint_count = 3 ;
void sigint_handler();
	
main() {
        signal( SIGINT, &sigint_handler );
        printf("main(): going into infinite loop, sigint_count == %d\n", 
                sigint_count);
        while( 1 ) {
            printf("main(): sigint_count == %d, pause() ....\n",
                    sigint_count );
            pause();
            printf("main(): return from pause().  sigint_count == %d\n",
                    sigint_count );
        }
}

void sigint_handler() {
        printf("sigint_handler():\n");
        if( -- sigint_count <= 0 ) {
            printf("sigint_handler(): exit() ... \n");
            exit( 1 );
        }
        signal( SIGINT, &sigint_handler ); /* System V */
        printf("sigint_handler(): sigint_count == %d\n",sigint_count);
}
----------------------------------------------------------------------

実行例
----------------------------------------------------------------------
% signal
main(): going into infinite loop, sigint_count == 3
main(): sigint_count == 3, pause() ....
^C
sigint_handler():
sigint_handler(): sigint_count == 2
main(): return from pause().  sigint_count == 2
main(): sigint_count == 2, pause() ....
^C
sigint_handler():
sigint_handler(): sigint_count == 1
main(): return from pause().  sigint_count == 1
main(): sigint_count == 1, pause() ....
^C
sigint_handler():
sigint_handler(): exit() ... 
%
----------------------------------------------------------------------
stty で intr に相当するキーを3回押す。