160 likes | 287 Views
シグナル通信. 普通の割込みと ソフトウェア割込み ソフトウェア割込みとシグナル キーボードからのシグナル 例外 ( exception ) キーボードからのシグナルの応用 シグナルの種類 ソフトウェア割込み(シグナル)の利用法 signal システム・コール signal プログラミング シグナル alarm プログラミング シグナル kill プログラミング. 普通の割込みと ソフトウェア割込み. Ctrl-C. 普通の割込み(ハードウェアによる割込み)は、オペレーティング・システム のカーネルにおいて利用されている。
E N D
シグナル通信 • 普通の割込みとソフトウェア割込み • ソフトウェア割込みとシグナル • キーボードからのシグナル • 例外 (exception) • キーボードからのシグナルの応用 • シグナルの種類 • ソフトウェア割込み(シグナル)の利用法 • signalシステム・コール • signalプログラミング • シグナルalarmプログラミング • シグナルkillプログラミング
普通の割込みとソフトウェア割込み Ctrl-C • 普通の割込み(ハードウェアによる割込み)は、オペレーティング・システム のカーネルにおいて利用されている。 • ソフトウェア割込みとは、本来はオペレーティング・システムのカーネルしか 使えない割込みの機能を、ソフトウェアにより実現して、一般の利用者プログ ラム(プロセス)でも使えるようにしたものである。 プロセス A プロセス B ソフトウェア割込み カーネル
ソフトウェア割込みとシグナル Ctrl-C • ソフトウェア割込みの機能は、シグナル(signal)という名前で実現 されている。 • シグナルとは、本来はプロセス間通信の一種で、あるイベントが起き たことを他のプロセスに知らせることである。 • シグナルで伝わるのは、あるイベントが 起きたかどうかだけで、イベントの種類の区別ができることがあるが、 データを送ることはできない。 プロセス A プロセス B プロセス間通信 シグナル カーネル
キーボードからのシグナル • プロセス間でシグナルにより通信をする他に、キーボードからシグナルを送ることも できる。 • キーボードからのシグナルは、「ソフトウェア割込み」として、プロセス1つひとつに割込みボタンが付いているようなものである。 プロセスA signal(SIGINT,stop); void stop() { … } プロセスB Ctrl-C シグナル
例外 (exception) • プログラムの中で例外 (exception)が起きた時にも、ハードウェアの割込みと同様に、ソフトウェ ア割込みが生じる。 • 例外 (exception)も、他のシグナルと同じように受け取ることができる。 プロセスA signal(SIGINT,stop); void stop() { … } プロセスB Ctrl-C 例外 (exception) シグナル
キーボードからのシグナルの応用 $ cat > gomi a b c [1]+ Stopped cat >gomi $ fg cat >gomi d e f $ cat gomi a b c d e f $ Ctrl-Z 再開 Ctrl-C
ソフトウェア割込み(シグナル)の利用法 • 受け側(割り込まれる方、シグナルを受け取る方) • 割込みハンドラの定義。割込みが起きた時に実行される関数を定義する。 • 割込みハンドラの登録。定義した関数を登録する。signal(2), sigvector(2), などを使う。 • 割込みマスク(割込みを禁止のビット・ベクトル)の制御。 sigsetmask(2) など。 • 送り側(割り込む方、シグナルを送る方) • 割込みの発生。kill(2) など。 • キーボード。 • 例外。 • タイマ割り込み。alarm(2)。 • 割り込みハンドラが設定されていない時には、プロセスは、デフォルトの動き をする。デフォルトには、次の3つがある。 • プロセスが終了させられる。 • プロセスが一時停止させられる。 • なにも起らない(シグナルが無視される)。 • signal の種類は、man 7 signal (Linux) で表示される。
シグナルを受け取ったときの処理を指定 インクルードファイル #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システム・コール
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(秒) は、指定した秒の経過後にSIGALRMを発生 • signal() で、割込み処理ハンドラ関数 func()を登録している。この段階で、関数 func() は呼び出されない。また、プログラムのどこからも、関数 func() は明示的には呼び出されていない。 • main() は、 alarm()で1秒後にSIGALRMの発生を指示、そして永久ループに入る。 • func() は、main() から呼び出されないが、割込みが発生すると実行され、 SIGALRMを受け付けてメッセージをプリントし、再び、 alarm()で1秒後にSIGALRMの発生を指示。 • 結果、毎秒、割込み処理ハンドラ関数 func() が呼び出され、メッセージをプリント。 alarm.c
シグナルalarmプログラミング(2/2) • pause() は、割込みを待つシステムコールである。システムコールの実行中に 割込みが発生するまで待つ。割込みが発生すると、割込み処理ハンドラの実行後にリターンする。 • signal() で、割込み処理ハンドラ関数 func()を登録している。この段階で、関数 func() は呼び出されない。また、プログラムのどこからも、関数 func() は明示的には呼び出されていない。 • main() は、 alarm()で1秒後にSIGALRMの発生を指示、そしてpause() により割り込みの発生を待つ。 • func() は、main() から呼び出されないが、割込みが発生すると実行され、 SIGALRMを受け付けてメッセージをプリント alarm-pause.c
シグナル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) • 指定したpidを持つプロセスが存在するか確認 • if(kill(pid,0) != EOF) プロセスは存在する kill-query-pid.c