Operating Systems. Exercise 03
I. プロセスへのシグナル送受信 (準備課題, 配点無し)
演習問題を解くために必要なシグナル制御のためのC言語インターフェースを説明します。
配点はありませんので、
シグナル制御インターフェイスについて知っている人はここを飛ばして、下のIIに進んでください。
実行中のプロセスに対してシグナルを送り、それをプログラム側で受けとることができます。
シグナルの受取側(プログラム)ではシグナルを受信したときに呼び出される関数を登録しておき、
シグナル送信は今回はターミナルからkillコマンドを使って送ります。
以下のプログラムでいろいろ実験してください。
[実験のために、プログラムを実行するターミナル(ktermなどのこと)と、
シグナルを送信する側のターミナルの計2つを用意しておくと良いでしょう]
シグナルSIGUSR1待ちプログラム (SignalTest)
#include <stdio.h>
#include <signal.h>
//プロトタイプ宣言を適宜
int main() {
int i;
//シグナルハンドラ関数を登録する
//コマンド(% kill -USR1 "プロセスID")などにより シグナルSIGUSR1が送信されたとき
//シグナルハンドラ関数SignalHandlerが呼び出されるようになる
signal(SIGUSR1, SignalHandler);
for (i=0; ; ++i) {
sleep(1); //すごい勢いで出力され重くなるので わざと1秒ずつ待っています
printf("%d\n", i);
}
return 0;
}
// signal SIGUSR1 handler
void SignalHandler(int code) {
printf("signal received\n");
//シグナルハンドラ関数の再登録
signal(SIGUSR1, SignalHandler);
}
ターミナル1 (シグナル待ちプログラム実行)
|
ターミナル2 (シグナル送信側)
|
II. プロセス間通信(配点100%)
課題1
課題:
演習1で作成したハノイの塔の問題を任意の引数で与えた個数の円盤に対して解くプログラムを
修正し、
シグナル"SIGUSR1"を受け取るごとに現在のハノイの塔の状況を出力するように改変してください。
例: プログラムの実行形式のファイル名を "ProcComm1"とし, 円盤数を"20"としたとき
ターミナル1 (ハノイの塔プログラム実行)
|
ターミナル2 (シグナル送信側)
|
導入: 課題1のプログラム中で, 関数Solveの中に円盤を移動する以下のようなコードが有ると思います。
ハノイの塔の円盤を移動する部分
*_naB = *_naA; //処理1 : 棒_Aから_Bへ移動
*_naA = 0; //処理2 : 移動元の_Aの円盤をクリア
もし"処理1"と"処理2"の間に偶然シグナルが発生しハノイの塔の状態を出力すると、
そのとき動かしている円盤が2つ現れてしまいます(クリティカルパス)。
クリティカルパスが発生する状況を再現するために, プログラムを以下のように
改変します
クリティカルパスの状況を再現
*_naB = *_naA; //処理1 : 棒AからBへ移動
sleep(1) //<--- わざと時間をかけ ここでシグナルが発生する状況を再現する
*_naA = 0; //処理2 : 移動元のAの円盤をクリア
改変したコードでシグナルを送る実験します。 すると、高確率で同じ円盤が2つ現れてしまいます
ターミナル1 (ハノイの塔プログラム実行)
|
ターミナル2 (シグナル送信側)
|
課題:
今回の改変後のコードのようなケースで、2重に円盤が出力されるという状況を
確実に回避する手段があるでしょうか?
有ればそのプログラムを, 無ければその理由を説明してください。
考え方:
シグナルを受信を確認したらすぐにDisplayするのではなく, シグナルを受け取ったことを記憶しておいて
確実に処理1と処理2が終わった後でDisplayするようにできないか?