時計やタイマーの管理も重要なシステム資源です。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.シグナルのところを見てください。