ネットワークプログラミング講座

シグナル通信
シグナル通信











普通の割込みとソフトウェア割込み
ソフトウェア割込みとシグナル
キーボードからのシグナル
例外 (exception)
キーボードからのシグナルの応用
シグナルの種類
ソフトウェア割込み(シグナル)の利用法
signalシステム・コール
signalプログラミング
シグナルalarmプログラミング
シグナルkillプログラミング
シグナル通信
普通の割込みとソフトウェア割込み


普通の割込み(ハードウェアによる
割込み)は、オペレーティング・シス
テム のカーネルにおいて利用され
ている。
ソフトウェア割込みとは、本来はオ
ペレーティング・システムのカーネ
ルしか 使えない割込みの機能を、
ソフトウェアにより実現して、一般の
利用者プログ ラム(プロセス)でも
使えるようにしたものである。
Ctrl-C
プロセス
A
プロセス
B
ソフトウェア割込み
カーネル
シグナル通信
ソフトウェア割込みとシグナル



ソフトウェア割込みの機能は、シグ
ナル(signal)という名前で実現 され
ている。
シグナルとは、本来はプロセス間通
信の一種で、あるイベントが起き た
ことを他のプロセスに知らせること
である。
シグナルで伝わるのは、あるイベン
トが 起きたかどうかだけで、イベン
トの種類の区別ができることがある
が、 データを送ることはできない。
Ctrl-C
プロセス
A
プロセス
B
プロセス間通信
シグナル
カーネル
シグナル通信
キーボードからのシグナル


プロセス間でシグナル
により通信をする他
に、キーボードからシ
グナルを送ることも で
きる。
キーボードからのシグ
ナルは、「ソフトウェア
割込み」として、プロセ
ス1つひとつに割込み
ボタンが付いているよ
うなものである。
プロセスA
プロセスB
signal(SIGINT,stop);
void stop() {
…
}
シグナル
Ctrl-C
シグナル通信
例外 (exception)


プログラムの中で例外
(exception)が起きた
時にも、ハードウェア
の割込みと同様に、ソ
フトウェ ア割込みが生
じる。
例外 (exception)も、
他のシグナルと同じよ
うに受け取ることがで
きる。
プロセスA
プロセスB
signal(SIGINT,stop);
void stop() {
…
}
シグナル
例外
Ctrl-C
(exception)
シグナル通信
キーボードからのシグナルの応用
$ cat > gomi
a
b
c
[1]+ Stopped
$ fg
cat >gomi
d
e
f
$ cat gomi
a
b
c
d
e
f
$
Ctrl-Z
cat >gomi
再開
Ctrl-C
シグナル通信
シグナルの種類
種類
発生原因
デフォルト動作
SIGHUP
端末のハングアップ
終了
SIGINT
Ctrl-C
終了
SIGQUIT
Ctrl-\
コアダンプ
SIGILL
不正な命令
コアダンプ
SIGTRAP
トレース
コアダンプ
SIGABRT
abort関数の実行
コアダンプ
SIGBUS
バスエラー
コアダンプ
SIGFPE
浮動小数点例外
コアダンプ
SIGKILL
killシグナル
終了
SIGUSR1
ユーザ定義シグナル
終了
SIGSEGV
不正なメモリ参照
コアダンプ
SIGUSR2
ユーザ定義シグナル
終了
SIGPIPE
バイプの破壊
終了
SIGALRM
alarmシステムコールからのタイマーシグナル
終了
SIGTERM
終了シグナル
終了
SIGCLD
子プロセスの停止、終了
無視
SIGCONT
いったん停止からの再開
SIGSTOP
プロセスのいったん停止
停止
SIGTSTP
Ctrl-Z
停止
シグナル通信
ソフトウェア割込み(シグナル)の利用法

受け側(割り込まれる方、シグナルを受け取る方)
 割込みハンドラの定義。割込みが起きた時に実行される関数を定
義する。
 割込みハンドラの登録。定義した関数を登録する。signal(2),
sigvector(2), などを使う。
 割込みマスク(割込みを禁止のビット・ベクトル)の制御。
sigsetmask(2) など。

送り側(割り込む方、シグナルを送る方)
 割込みの発生。kill(2) など。
 キーボード。
 例外。
 タイマ割り込み。alarm(2)。

割り込みハンドラが設定されていない時には、プロセスは、デフォルト
の動き をする。デフォルトには、次の3つがある。
 プロセスが終了させられる。
 プロセスが一時停止させられる。
 なにも起らない(シグナルが無視される)。

signal の種類は、man 7 signal (Linux) で表示される。
シグナル通信
signalシステム・コール
シグナルを受け取ったときの処理を指定





インクルードファイル

#include <signal.h>
書式

sighandler_t signal(int signum, sighandler_t
sighandler);
引数

signum シグナルの種類

sighandler シグナルハンドラのアドレス

デフォルト動作: sighandler=SIG_DFL

シグナルを無視: sighandler=SIG_IGN
戻値

成功時 前回のシグナルハンドラのアドレス

失敗時 SIG_ERR
使用例

void stop();

signal(SIGINT, &stop);
プロセス
signal(SIGINT,stop);
void stop() {
…
}
シグナル
シグナル通信
signalプログラミング(1/2)
signal-int.c




signal() で、割込み処理ハンドラを
関数 sigint_handler()登録している。
この段階で、関数 sigint_handler()
は呼び出されない。また、プログラ
ムのどこからも、関数
sigint_handler() は明示的には呼び
出されていない。
main() は、無限ループになってい
る。
pause() は、割込みを待つシステ
ムコールである。システムコール
の実行中に 割込みが発生するま
で待つ。発生すると、割込み処理
ハンドラの実行後にリターンする。
sigint_handler() は、main() から呼
び出されないが、割込みが発生す
ると実行される。内部では、大域
変数 sigint_count を減らして、0 以
下になれば終 了している。
シグナル通信
signalプログラミング(2/2)
timer.c



signal() で、割込み処理ハンドラ関
数 sigint_handler()を登録してい
る。この段階で、関数
sigint_handler() は呼び出されな
い。また、プログラムのどこから
も、関数 sigint_handler() は明示的
には呼び出されていない。
main() は、 "."を永久ループにより
1秒毎に出力。
sigint_handler() は、main() から呼
び出されないが、割込みが発生す
ると実行され、SIGINT を受け付け
て終了(経過時間をプリント)。
シグナル通信
シグナルalarmプログラミング(1/2)




alarm.c

alarm(秒) は、指定した秒の経過後
にSIGALRMを発生
signal() で、割込み処理ハンドラ関
数 func()を登録している。この段階
で、関数 func() は呼び出されない。
また、プログラムのどこからも、関数
func() は明示的には呼び出されて
いない。
main() は、 alarm()で1秒後に
SIGALRMの発生を指示、そして永
久ループに入る。
func() は、main() から呼び出されな
いが、割込みが発生すると実行され、
SIGALRMを受け付けてメッセージを
プリントし、再び、 alarm()で1秒後に
SIGALRMの発生を指示。
結果、毎秒、割込み処理ハンドラ関
数 func() が呼び出され、メッセージ
をプリント。
シグナル通信
シグナルalarmプログラミング(2/2)




alarm-pause.c
pause() は、割込みを待つシステム
コールである。システムコールの実行
中に 割込みが発生するまで待つ。割
込みが発生すると、割込み処理ハン
ドラの実行後にリターンする。
signal() で、割込み処理ハンドラ関数
func()を登録している。この段階で、関
数 func() は呼び出されない。また、プ
ログラムのどこからも、関数 func() は
明示的には呼び出されていない。
main() は、 alarm()で1秒後に
SIGALRMの発生を指示、そして
pause() により割り込みの発生を待つ。
func() は、main() から呼び出されない
が、割込みが発生すると実行され、
SIGALRMを受け付けてメッセージをプ
リント
シグナル通信
シグナルkillプログラミング(1/3)
kill-group.c
kill(0,1)


自分と同じグループIDを
持つプロセス全てに、プ
ロセスの強制終了シグ
ナルを送信
(シグナル番号に 0 を入
れる)
シグナル通信
シグナルkillプログラミング(2/3)
kill-pid.c
kill(pid,1)


指定したpidを持つプロ
セスに、プロセスの強制
終了シグナルを送信
(シグナル番号に pid を
入れる)
シグナル通信
シグナルkillプログラミング(3/3)
kill(pid,0)


kill-query-pid.c
指定したpidを持つ
プロセスが存在する
か確認
if(kill(pid,0) != EOF)
プロセスは存在する