時計やタイマーの管理も重要なシステム資源です。UNIXシステムでは時刻は グリニッジ標準時で1970年1月1日0時0分0秒を基準とした通算秒数で表わしま す。gettimeofdayシステムコールで取得できます。
#include <sys/time.h> struct timeval tv; struct timezone tz; tz.tz_minuteswest = 900; /* 日本時間は15時間西(9時間東)*/ tz.tz_dsttime = DST_NONE; /* 夏時間は採用せず */ gettimeofday( &tv, &tz );
これで、tv.tv_secに通算秒数が、tv.tv_usecにマイクロ秒で1秒以下の端数が 返ります。使う場合は通常、これらを年月日、時分秒に計算し直す必要があり ます。そういう意味ではあまり使いやすいものではありません。Cのランタイ ムライブラリーに用意されている時間関係の関数のほうが使いやすいでしょう。
#include <time.h> #include <sys/types.h> #include <sys/time.h> time_t tloc; struct tm *lt; char *alt; tloc = time( NULL ); /* 現在時をGMTで取得 */ lt = localtime( & tloc ); /* 現地時間に変換しtm構造体に返す。*/ alt = asctime( lt ); /* ASCII文字列に変換 */
構造体tmは時刻を表わす要素をメンバーに持つもので、次のような構造体メン バーを持っています。
struct tm { int tm_sec; /* 秒 ( 0- 59 ) */ int tm_min; /* 分 ( 0-59 ) */ int tm_hour; /* 時 ( 0-23 ) */ int tm_mday; /* 日 ( 1-31 ) */ int tm_mon; /* 月 ( 0-11 ) */ int tm_year; /* 年 ( 西暦から1900を引いた数 ) */ int tm_wday; /* 曜日 ( 日曜日が0 ) */ int tm_yday; /* 正月からの日数 ( 0-365 ) */ int tm_isdst; /* 夏時間中なら1 */ char *tm_zone; /* 現地時間をあらわす文字。JSTなど */ long tm_gmtoff; /* GMTからのオフセット秒数 */ };
asctim関数はtm構造体のデータを「Wed Aug 24 18:30:15 1994\n
」のような文
字列に変換します。localtimeとasctimeを両方呼び出す関数がctimeです。最
も簡単に日付を表示するには
printf( "Time = %s", ctime( time( NULL ) ) );
等とやれば良いことになります。任意のフォーマットで時刻を表現するための strftimeやstrptimeといった関数も用意されています。例えば時刻のみを 23:59:59のような表現で表示したければ
time_t t; struct tm * lt; char buf[ 64 ]; t = time( NULL ); lt = localtime( & t ); strftime( buf, 64, "%H:%M:%S", lt );
というようにやります。実は%H:%M:%Sは%Tと指定するのとおなじなのです が。日付をVMSでおなじみの形01-Jan-1996のように表すには
strftime( buf, 64, "%d-%b-%Y", lt );
ということになります。詳しい解説はman strftimeで見てください。
時刻をプログラムの中で設定するためのシステムコールも用意されています が、スーパーユーザでなけば実行できません。また、そのようなプログラムを 書く必要は一般的にはありませんのでここでは触れません。
時刻のほかにインターバルタイマーの仕組みも用意されています。インター バルタイマーはカウントダウンタイマーで、繰り返し繰り返し一定の時間を数 えるものです。そして残り時間が0になったところで割り込みをかけることが 可能です。次の例を見てください。
#include <sys/time.h> struct itimerval itimer; itimer.it_interval.tv_sec = 0; /* 繰り返し周期 */ itimer.it_interval.tv_usec = 100000; /* 100,000マイクロ秒(0.1秒) */ itimer.it_value.tv_sec = 0; itimer.it_value.tv_usec = 100000; setitimer( ITIMER_REAL, &itimer, NULL );
setitimerシステムコールはインターバールタイマーをスタートさせます。 itimerval構造体は二つのtimeval構造体をメンバーに持っています。一つは it_valueで、最初にインターバルタイマーにセットされる時間、もう一つは it_intervalで、これはインターバルタイマーが0になったときセットされる値 です。この例ではどちらもtv_secが0でtv_usecが10000 0ですから100000マイ クロ秒つまり0.1秒がセットされます。ITIMER_REALは世の中の普通の時間です。 実際にかかる時間です。このかわりにITIMER_VIRTUALを指定するとプロセスが 実行している間だけ進む時間になります。
タイマーの中身はgetitimerシステムコールで読むことができます。
getitimer( ITIMER_REAL, &itimer );
引数の意味はsetitimerと同じですが、it_value構造体に現在のタイマーの値 が返されます。これを使えばプログラムの実行に要した時間などをかなり正確 に測定することができます。たた、実装上マイクロ秒で指定しますがシステム の時計の精度はそれほど良くはありません。またこのタイマーが0になる度に プログラムに割り込みをかけることはできますが、その精度は実はずっと荒い ものです。割り込みのかけかたは8.2.7.シグナルのところを見てください。