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

システム・プログラム

                                       電子・情報工学系
                                       新城 靖
                                       <yas@is.tsukuba.ac.jp>

このページは、次の URL にあります。
http://www.hlla.is.tsukuba.ac.jp/~yas/coins/syspro-2000/2000-05-01 /process-signal.html
あるいは、次のページから手繰っていくこともできます。
http://www.hlla.is.tsukuba.ac.jp/~yas/coins/
http://www.is.tsukuba.ac.jp/~yas/index-j.html

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

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

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

UNIXでは、ソフトウェア割込みの機能は、シグナル(signal)という名前で実現 されている。シグナルとは、本来はプロセス間通信の一種で、ある事象が起き たことを他のプロセスに知らせることである。ここで伝わるのは、ある事象が 起きたかどうかだけで、引数などを付けることはできない。UNIXでは、プロセ ス間でシグナルにより通信をする他に、キーボードからシグナルを送ることも できる。これは、「ソフトウェア割込み」として、プロセス1つひとつに割込 みボタンが付いているようなものである。また、プログラムの中で例外 (exception)が起きた時にも、ハードウェアの割込みと同様に、ソフトウェ ア割込みが生じる。これも、他のシグナルと同じように受け取ることができる。

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

割り込みハンドラが設定されていない時には、プロセスは、デフォルトの動き をする。デフォルトには、次の3つがある。 signal の種類は、man 5 signal (SGI IRIX) で表示される。

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


----------------------------------------------------------------------
   1:	/*
   2:	        signal-int.c -- SIGINT を3回受け付けて終了するプログラム。
   3:	        ~yas/syspro1/proc/proc/signal-int.c
   4:	        $Header: /home/lab2/OS/yas/syspro1/proc/RCS/signal-int.c,v 1.3 1998/06/15 12:24:36 yas Exp $
   5:	        Start: 1997/05/26 18:38:38
   6:	*/
   7:	
   8:	#include <stdio.h>
   9:	#include <signal.h>
  10:	
  11:	int sigint_count = 3 ;
  12:	void sigint_handler();
  13:	
  14:	main()
  15:	{
  16:	        signal( SIGINT, &sigint_handler );
  17:	        printf("main(): going into infinite loop, sigint_count == %d\n", 
  18:	                sigint_count);
  19:	        while( 1 )
  20:	        {
  21:	            printf("main(): sigint_count == %d, pause() ....\n",
  22:	                    sigint_count );
  23:	            pause();
  24:	            printf("main(): return from pause().  sigint_count == %d\n",
  25:	                    sigint_count );
  26:	        }
  27:	}
  28:	
  29:	void sigint_handler()
  30:	{
  31:	        printf("sigint_handler():\n");
  32:	        if( -- sigint_count <= 0 )
  33:	        {
  34:	            printf("sigint_handler(): exit() ... \n");
  35:	            exit( 1 );
  36:	        }
  37:	        signal( SIGINT, &sigint_handler ); /* System V */
  38:	        printf("sigint_handler(): sigint_count == %d\n",sigint_count);
  39:	}
----------------------------------------------------------------------

実行例。

----------------------------------------------------------------------
% stty -a [←]
speed 9600 baud; line = 1; 48 rows; 80 columns
intr = ^C; quit = ^\; erase = ^H; kill = ^U; eof = ^D; eol = ^@; old-swtch = ^Z; susp = ^Z
lnext = ^V; werase = ^W; rprnt = ^R; flush = ^O; stop = ^S; start = ^Q; dsusp = ^Y
parenb -parodd cs8 -cstopb hupcl cread -clocal -cnew_rtscts -loblk 
-ignbrk -brkint -ignpar -parmrk -inpck -istrip -inlcr -igncr icrnl -iuclc 
ixon -ixany -ixoff -imaxbel 
isig icanon iexten -xcase echo echoe echok echoke echoctl -echoprt -echonl -noflsh -flusho -pendin -tostop 
opost -olcuc onlcr -ocrnl -onocr -onlret -ofill -ofdel 
% ./signal-int [←]
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回押す。

■練習問題

★練習問題59 kill コマンドによるシグナルの発生

signal-int.c のプロ グラムを動かし、kill コマンドを使って SIGINT (kill -INT)でシグナルを送 りなさい。そして、キーボードから intr のキー^Cを打った時と動 作を比較しなさい。

ヒント:kterm を2つ開いて、片方でこのプログラムを動かし、片方で kill コマンドを動かす。kill 引数として必要な PID は、ps コマンドで調べる。

★練習問題60 killコマンド

kill コマンドと似た動きをするプログラムを作りなさい。

★練習問題61 ^Cで死なないプロセス

SIGINT シグナルを発生させても終了しないプロセスを 作りなさい。

ヒント:そのシグナルを無視(SIG_IGN)するように設定する。

★練習問題62 割込み処理中の割込み

割込み処理の最中に、同じ割込みが発生した時にはどうなるかを調べなさい。

★練習問題64 BSD系のUNIXのシグナルのあつかい

SGI IRIX では、次のようにコンパイル時に _BSD_SIGNALS というマクロを定 義すると BSD 系の UNIX のシグナル機能が使える。
	cc -D_BSD_SIGNALS -o prog prog.c
BSD 系では、一度登録したシグナルは、ハンドラの中で再登録する必要はない。 このことを調べなさい。

また、シグナル・ハンドラの中でシグナルを受けた時の動きを調べなさい。

くわしくは、man 3b signal で表示される。


↑[もどる] ←[4月24日] ・[5月01日] →[5月08日] [課題]
Last updated: 2000/04/30 21:15:08
Yasushi Shinjo / <yas@is.tsukuba.ac.jp>