ソフトウェア設計及び演習2017

時間の計測

GLib::チュートリアルの中にある,イベントループを用いた方が簡単かもしれません.

以下は過去の事例.

経過時間を計るプログラム

解説

ゲームのプログラムなどで,時間の経過によって処理を行う場合があります. この例では,1秒毎にある変数の値を1ずつ増やし,その値(経過 秒)を表示するプログラムです.

プログラム中で,

  while(1) {
      sleep(10);
      if (newClock>Clock) {
        Clock = newClock;   
        printf("Clock(%d) uClock(%d)\n", Clock, uClock);
      }

という個所がありますが, while の中では,

  • sleep(10): 10秒間プログラムがスリープ(停止状態)
  • newClock 変数と Clock変数の値が異なると,Clock を更新し,その値を表示

を繰り返しています.しかし,このループ中 newClock 変数の値を変更している個所はありません.

NewClock の値を変更しているのは,

  • TimerHnadler 関数の中ですが,この関数を呼び出しているところはありません.
  • これは Unix のシグナルという機構を使って実現されています.

シグナルは,プログラム(厳密にはプロセス)に対する割り込みを伝える機構です.

プロセスが

  • シグナルを処理する関数を登録しておくことで,
  • シグナルを受け取った時に処理関数が実行されます.

この処理は,

  • プログラムの実行を一時中断し,
  • シグナルに対する処理が行われ,
  • その処理後は,中断された個所から再開されます.

まず,1秒毎の目覚まし時計の設定方法ですが,

  struct itimerval mytimer;
  (mytimer.it_interval).tv_sec = 1;
  (mytimer.it_interval).tv_usec = 0;
  (mytimer.it_value).tv_sec = 1;
  (mytimer.it_value).tv_usec = 0;

itimervalは時間を設定するための構造体です.ここでは1秒後に鳴る目覚まし時計を指定しています.

目覚まし時計を仕掛けるのが

  setitimer(ITIMER_REAL, &mytimer, NULL);

そのSIGARLMが起こった時に呼び出される関数が TimerHandler ですが,それを

  signal(SIGALRM, TimerHandler);

で指定しているわけです.

TimerHandler関数が行うことは,

void TimerHandler() 
{
  newClock = Clock+1;
  signal(SIGALRM, TimerHandler);
}

NewClockの値に1を足して,再度,シグナル SIGARLM 処理関数を指定しています.


最終更新日:2017/04/03 09:14:20