- 1. 概要
- 2. gettimeofday, settimeofday 日付と時刻の取得 / 設定
- 3. nanosleep n(ナノ)秒単位でスリープ
- 4. timeradd, timersub, timercmp 日時計算
1. 概要
ここでは、「time」や「localtime_r」で取得する時刻より精度の高い時刻の取得や、日時計算のメモをしています。
2. gettimeofday, settimeofday 日付と時刻の取得 / 設定
#include <sys/time.h>
int gettimeofday(struct timeval *tp, struct timezone *tzp);
int settimeofday(const struct timeval *tp, const struct timezone *tzp);
当然、「gettimeofday」で取得、「settimeofday」で設定になります。
「struct timeval」型は 以下の形式。
struct timeval
{
long tv_sec; // 1970 年 1月 1日からの秒数
long tv_usec; // およびμ(マイクロ)秒数
};
「struct timezone」型は、タイムゾーンを表すもので、本来、夏時間を定義して日時を扱うためのものでしたが、コンピュータで扱うには不向き(政治的問題が大きくからむ)であることから廃止の方向ですので、明示的に 「NULL」を引数にします。
そもそも、どっかの馬鹿の政治家くらいしか、夏時間なんてことは考えないのですよ。
4. nanosleep n(ナノ)秒単位でスリープ
#include <time.h>
int nanosleep(const struct timespec *rqtp, struct timespec *rmtp);
基本は「rqtp」で指定した時間スリープします。
きっちり待ち時間分スリープした場合は、戻り値は「0」になります。
スリープ中にシグナルによって起動された場合、「rmtp」が「NULL」でなければ「rmtp」に残りの時間が設定されます。
このとき戻り値には「-1」が設定され、「error」に「EINTR」が設定されます。
「struct timespec」型は、以下の形式。
struct timespec
{
time_t tv_sec; // 秒
long tv_nsec; // n(ナノ)秒
};
いささか汎用性に欠けるので、例えば、精度をミリ秒単位までとし、シグナルが発生しないものとすれば例えば。
int myNanosleep(int second, int millisecond)
{
struct timespec rqtp = {};
struct timespec rmtp = {};
rqtp.tv_sec = second;
rqtp.tv_nsec = millisecond * 1000 * 1000;
return nanosleep(&rqtp, &rmtp);
}
のような関数を書けば、秒単位・ミリ秒単位で実行を停止させることができます。
3. timeradd, timersub, timercmp 日時計算
これは内容は関数でなくマクロらしいです。
#include <sys/time.h>
void timeradd(struct timeval *a, struct timeval *b, struct timeval *res);
void timersub(struct timeval *a, struct timeval *b, struct timeval *res);
int timercmp(struct timeval *a, struct timeval *b, CMP);
「timeradd」は「a」と「b」を足した結果を「res」に返します。
「timersub」は「a」から「b」を引いた結果を「res」に返します。
「timercmp」は「a」と「b」を「CMP」に示す記号が真(0以外)か偽(0)かを返します。
「CMP」には「<」「>」「!=」のいずれかを使います。
これは、文字列やキャラクタではないので、ダブルコーテーションやシングルコーテーションで囲まないようご注意ください。
「>=」や「==」もコンパイルエラーにはなりませんが、コンパイラによって結果が異なることがあるらしい。
下記のソースを書いて。
#include <limits.h>
#include <stdio.h>
#include <sys/time.h>
static void timerset(struct timeval* c, time_t* time_c);
int main(int argc, char* argv[])
{
for (int i=0; i<5; i++)
{
struct timeval c = {};
time_t time_c = 0;
timerset(&c, &time_c);
printf("前回との時刻差は[%02ld]秒です\n", time_c);
printf("前回との時刻差は[%02ld.%06ld]秒です\n", c.tv_sec, c.tv_usec);
printf("\n");
}
return 0;
}
void timerset(struct timeval* c, time_t* time_c)
{
static unsigned char virgin = 1;
static struct timeval a = {};
struct timeval b = {};
static time_t time_a = 0;
time_t time_b = 0;
if (virgin != 0)
{
gettimeofday(&a, NULL);
time_a = time(NULL);
virgin = 0;
return;
}
gettimeofday(&b, NULL);
time_b = time(NULL);
*time_c = time_b - time_a;
time_a = time_b;
timersub(&b, &a, c);
a = b;
}
実行すると下記の結果が得られます。
sh: /home/kitayama/lang/cpp/time/timersub: not found
当たり前のことですが、「time」では得られない差を「gettimeofday」で得ることができるわけです。
|