システム・プログラム 電子・情報工学系 新城 靖 <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のソフトウェア割込み(シグナル)を使うには、次のようなことが必要で ある。
ソフトウェア割り込みは、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 で intr に相当するキーを3回押す。---------------------------------------------------------------------- % stty -aspeed 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() ... %
----------------------------------------------------------------------
signal-int.c のプロ グラムを動かし、kill コマンドを使って SIGINT (kill -INT)でシグナルを送 りなさい。そして、キーボードから intr のキー^Cを打った時と動 作を比較しなさい。
ヒント:kterm を2つ開いて、片方でこのプログラムを動かし、片方で kill コマンドを動かす。kill 引数として必要な PID は、ps コマンドで調べる。
ヒント:そのシグナルを無視(SIG_IGN)するように設定する。
cc -D_BSD_SIGNALS -o prog prog.cBSD 系では、一度登録したシグナルは、ハンドラの中で再登録する必要はない。 このことを調べなさい。
また、シグナル・ハンドラの中でシグナルを受けた時の動きを調べなさい。
くわしくは、man 3b signal で表示される。