nanosleep
パート 3 として, nanosleep
(2) を使います.
名前から容易に想像できるように, ナノ秒 (0.000000001 秒!)
単位で動作を止めることができる (?) 関数です. 使い方は,
止めたい時間を指定した struct timespec
な変数
req
に対して, nanosleep(&req, NULL)
とすれば OK です.
struct timespec
は,
time_t
な要素 tv_sec
と
long
な要素 tv_nsec
から成り,
前者に秒単位, 後者にナノ秒単位で止める時間を指定します.
man nanosleep の BUGS を読むとわかりますが,
the normal kernel timer mechanism
に基づいているので,
引数に指定された秒数に加えて,
休んでいたプロセスが実行可能になるまでの時間 (10 ミリ秒程度)
が余計にかかるようです.
おなじみ (?) の gettimeofday
(2) を使います.
SLEEP_NSEC
ナノ秒だけ休んで時間を計測するというループを
LOOP
回繰り返すという, 今までと同じプログラム.
11 行目では 20000000 ナノ秒 = 20 ミリ秒を設定しています.
21,22 行目で,nanosleep
に渡す引数
treq
を作成しています.
1 /* 2 * test_nanosleep.c 3 * nanosleep を使って, 間隔をあけるテスト 4 */ 5 6 #include <stdio.h> 7 #include <unistd.h> 8 #include <sys/time.h> 9 #include <time.h> 10 11 #define SLEEP_NSEC 20000000 12 #define LOOP 10 13 14 int main() 15 { 16 int i; 17 struct timeval tv[LOOP]; 18 struct timezone tz; 19 struct timespec treq, trem; 20 21 treq.tv_sec = (time_t)0; 22 treq.tv_nsec = SLEEP_NSEC; 23 24 for(i=0; i<LOOP; i++){ 25 nanosleep(&treq, &trem); 26 gettimeofday(tv + i, &tz); 27 } 28 29 for(i=0; i<LOOP; i++){ 30 printf("%3d : %ld:%06ld\n", i, tv[i].tv_sec, tv[i].tv_usec); 31 } 32 33 return 0; 34 }
まずは実行結果. よく見ると, 30 ミリ秒の間隔が空いています. やっぱり, 指定した 20 ミリ秒に加えて, 10 ミリ秒が余計にかかっているようです.
0 : 890377532:454773 1 : 890377532:484678 2 : 890377532:514672 3 : 890377532:544669 4 : 890377532:574668 5 : 890377532:604672 6 : 890377532:634669 7 : 890377532:664669 8 : 890377532:694704 9 : 890377532:724671
次の例は, SLEEP_NSEC
を 200 ミリ秒にしてみました.
やぁっぱり 210 ミリ秒の間隔になってますねぇ. しかも,
マイクロ秒の位 (下から 3 桁) がほぼ揃っているのがニクイですね.
0 : 890378510:824762 1 : 890378511:034672 2 : 890378511:244678 3 : 890378511:454669 4 : 890378511:664667 5 : 890378511:874668 6 : 890378512:084669 7 : 890378512:294666 8 : 890378512:504667 9 : 890378512:714675
Copyright (C) 1998, Masahiro SATO