セマフォ、イベント駆動プログラミング 10/27

課題1

バッファサイズが n(固定)の Producer/Consumer problem を実演するプログラムを作成せよ。バッファはリングバッファとせよ。

  1. Producer は繰り返しデータを作成し、一つづつバッファに書き込む。 バッファが一杯の時には空きができるまで待つ。 バッファが一杯でないのに待ってはいけない。
  2. Consumer はバッファから一つづつデータを受け取る。 バッファが空の時はデータが書き込まれるまで待つ。 バッファが空でないのに待ってはいけない。
  3. Consumer は Producer が作成した順序でデータを受け取らなくてはならない。

Procuder が遅い場合、Consumer が遅い場合の両者についてテストをし、 データの洩れや重複がおこらないことを確認せよ。

提出課題

  1. 課題1のプログラム、テスト内容とその結果

以降はセマフォを自作するための課題である。

課題2 pause ()

pause() はプロセス/スレッドを blocked(waiting) 状態にするシステムコールである。 pause.cpp を実行して、このプログラムが(あまり) CPU を利用せず、 かつ終了しないことを確認せよ。

課題3 シグナルとシグナルハンドラ

プロセス/スレッドがシグナルを受け取ると、 処理が中断され、シグナルハンドラが実行される。 シグナルハンドラの処理が終ると、中断していた処理が再開する。

pause() などで blocked 状態にあったプロセス/スレッドがシグナルを受け取ると Ready 状態になる。そしてシグナルハンドラが実行された後、 処理は pause()などの次から再開する。

  1. シグナルはシェルから kill コマンドで発生させることができる。man kill で kill コマンドの使い方と、シグナルの種類について調べよ。

    使用例: kill -USR1 1234
    注:シグナル名の前にハイフンが必要です。

  2. signal-1.cpp を実行して、そのプロセスに USR1 シグナルを複数回送って見よ。また、USR2 シグナルを送って見よ。

課題4 スレッドとシグナル

pthread_kill を使うとスレッド間でシグナルをやりとりできる。 signal-2.cpp の実行結果を予測し、 実際の結果と比較検討せよ。

課題5 pause() とシグナルの落し穴、 シグナルのマスキングと sigsuspend()

  1. 課題3の signal-2.cpp の main() 中の sleep(1) を削除して実行し、 動作を確認せよ。なぜ、そのような結果になるのか考えよ。

  2. この問題を避けるには signal-3.cpp の様にする。pthread_sigmask() と sigsuspend() の使い方と意味を理解せよ。

sigaction( int signum, struct sigaction * new ,struct sigaction * old )
シグナルハンドラの登録を行う。シグナルハンドラはすべてのスレッドに共通する。 スレッド毎に違うハンドラを登録することはできない。

pause()
何もせず、シグナルが届くのを待つ。シグナルが届くと、 シグナルハンドラが呼ばれ、ハンドラ実行後、pause() の後から実行が 再開される。

pthread_sigmask( int how, const sigset_t * new, sigset_t * old)
シグナルをマスクする。シグナルは無視される(捨てられる)のではなく、 「保留」され、マスクされていた間に発生していたシグナルは、マスクが解除 されると、その時点で処理される。(ハンドラが呼ばれる。)

マスクは、スレッド毎に設定できる。子スレッドで何もマスクを設定しないと 親スレッドのマスクが受け継がれる。

sigsuspend( const sigset_t * mask )
マスクの設定(解除)と pause() をアトミックに行う。これによって、「待つ」 準備ができる前にシグナルが処理されてしまうことを避ける。

sigset_t
シグナルの集合を指定するためのデータ型。 sigemptyset で集合を空にして、 sigaddset でシグナルを追加する。 シグナルをマスクするときに、マスクしたいシグナルをこの型のデータで指定する。 空集合でマスクを設定すると、全てのマスクが解除される。

課題6 セマフォの自作

以下の雛型、ヒントを参考に class MySemaphore を作れ。 作成したクラスを用いて Producer/Consumer Problemの実演プログラム が正しく実行できること。

雛型、ヒント