sleep

目次

おやすみなさい

一定時間だけプログラムの実行を止める方法のその 1 として, sleep(3) を使います. なお, sleep(1) というコマンドもあるので, マニュアルを見るときは man 3 sleep とします. 使い方は簡単で, 引数に止まる秒数 (もちろん整数, 正確には unsigned int) を与えてやれば, その間プログラムは止まってくれます.

プログラムが止まっているときは, CPU も止まるのか? 答えはノー. プログラムの実行が止まっている間, CPU は平然と別の仕事をしています. マルチタスクなんで, 当たり前といえば当たり前ですね.

時を計りしもの

本当に, sleep は指定した時間だけ眠ってくれるのか? それを調べるためには, sleep の前後で時間を計測してやる必要があります. 時間を計ってくれる関数には, time(2) があります. こいつは, グリニッジ標準時で 1970 年 1 月 1 日 0 時 から流れ去った時間を, 秒単位で返してくれます. グリニッジ標準時でということは, コンピュータの世界では日本は 1970 年 1 月 1 日 9 時から始まってるんですね. time の使い方も簡単で, time_t な変数 t に対して, t = time() とか time(&t) とかすれば OK (のはず) です.

でもここでは, gettimeofday(2) を使います. 理由は, gettimeofday だと, 1970 年 1 月 1 日 0 時からの経過時間をマイクロ秒 (0.000001 秒!) 単位で教えてくれるから. 使い方は, struct timeval な変数 tv と, struct timezone な変数 tz に対して, gettimeofday(&tv, &tz) とやれば OK. tv.tv_sec に秒の部分が, tv.tv_usec にマイクロ秒の部分が入ってます. なお tv.tv_usec は, 7 桁以上にはならないでしょう. tz は, 今回は面倒なので省略.

プログラム例

というわけで, 実験したプログラム. SLEEP_SEC 秒だけ sleep で休み, その後に gettimeofday で時刻を調べるという作業を, LOOP 回だけ実行します. 時刻は tv[LOOP] という配列に格納し, 全てが終わってから出力します.

21 行目. 本来なら gettimeofday(&(tv[i]), &tz) とするのが筋でしょうが, より速くを目指したいので, tv のほうは直接ポインタを指定するようにしています. これで, どれだけ速いのかはわかりませんが.

 1  /*
 2   * test_sleep.c
 3   * sleep を使って, 間隔をあけるテスト
 4   */
 5
 6  #include <stdio.h>
 7  #include <unistd.h>
 8  #include <sys/time.h>
 9
10  #define SLEEP_SEC 10
11  #define LOOP 5
12
13  int main()
14  {
15    int i;
16    struct timeval tv[LOOP];
17    struct timezone tz;
18
19    for(i=0; i<LOOP; i++){
20      sleep(SLEEP_SEC);
21      gettimeofday(tv + i, &tz);
22    }
23
24    for(i=0; i<LOOP; i++){
25      printf("%3d : %ld:%06ld\n", i, tv[i].tv_sec, tv[i].tv_usec);
26    }
27
28    return 0;
29  }

実行結果

普通 (?) の実行結果. 良く見るとわかりますが, 1 ミリ秒程度の誤差があるけれど, 10 秒という時間を計測しているということを考えればすごいことですね.

  0 : 890298243:849071
  1 : 890298253:848975
  2 : 890298263:848975
  3 : 890298273:848976
  4 : 890298283:848976

次の例はいじわるして, プログラムの実行中に kterm を立ち上げたり du したりしたときのものです (う〜む, 私一人で 100M も使っていたのか…). 3 〜 4 ミリ秒の単位で狂ってきますね. マルチタスクな OS の宿命か. ま, 1% の誤差なら許してくれるでしょう.

  0 : 890299088:609103
  1 : 890299098:611411
  2 : 890299108:611900
  3 : 890299118:608997
  4 : 890299128:609005


[うさぎ]

m@sa.to