time wrapper
ふと思い付き、gettimeofday()/setttimeofday()のテスト用に作成しました。
元ネタは、failmallocです。
とはいえ、思い付きでさらっと作成したのでバグがあるかも。
Linuxでは時間計測にはgettimeofday()をよく使用します。
時間取得には他にもありますが、なぜgettimeofday()を使用する理由は
システム全体の時間が欲しいが為です。
例えばclock_gettime()はプロセスが実際に動作した時間を返すので
実際の経過時間が分かりません。
かといってtime()では精度が足りません。
ここでgettimeofday()の欠点は時刻の取得なのでsettimeofday()で過去に戻されると、
問題が発生します。
gettimeofday() //1: settimeofday() //ここで過去に戻す。 gettimeofday() //2:1よりも過去になる。 //ここで2-1で経過時間を求める
で大抵はsettimeofday()など使わないので問題がないのですが、
上記の場合問題が発生します。
また、settimeofday()はroot権限が必要なのでデバッグ/テスト時には
使用したくありません。
しかしこれを使えばシステムに影響をあたえずにデバッグ/テストを行えます。
#include <stdio.h> #include <dlfcn.h> #include <unistd.h> #include <sys/time.h> static void init(void) __attribute__((constructor)); static void fini(void) __attribute__((destructor)); static int (*lib_gettimeofday)(struct timeval *tv, struct timezone *tz); static int (*lib_settimeofday)(const struct timeval *tv , const struct timezone *tz); static int settime_flg = -1; static struct timeval diff_time; static void init(void){ lib_gettimeofday = dlsym(RTLD_NEXT, "gettimeofday"); if (lib_gettimeofday == 0){ _exit(1); } lib_settimeofday = dlsym(RTLD_NEXT, "settimeofday"); if (lib_settimeofday == 0){ _exit(1); } } static void fini(void){ return; } int gettimeofday(struct timeval *tv, struct timezone *tz){ int ret; struct timeval now; double tmp; ret = lib_gettimeofday(&now, tz); if(settime_flg < 0){ tv->tv_sec = now.tv_sec; tv->tv_usec = now.tv_usec; return ret; } tmp = ((double)now.tv_sec + (double)now.tv_usec/1000000) - ((double)diff_time.tv_sec + (double)diff_time.tv_usec/1000000); tv->tv_sec = (long)tmp; tv->tv_usec = tmp - tv->tv_sec; return 0; } int settimeofday(const struct timeval *tv , const struct timezone *tz){ int ret; struct timeval now; double diff; struct timezone ltz; if(tz != NULL){ ltz.tz_minuteswest = tz->tz_minuteswest; ltz.tz_dsttime = tz->tz_dsttime; } ret = lib_gettimeofday(&now, <z); if(ret < 0){ return -1; } diff = ((double)now.tv_sec + (double)now.tv_usec/1000000) - ((double)tv->tv_sec + (double)tv->tv_usec/1000000); diff_time.tv_sec = (long)diff; diff_time.tv_usec = diff - diff_time.tv_sec; settime_flg = 1; return 0; }
$ gcc -Wall -D_GNU_SOURCE -fPIC -shared -o time_wrapper.so time_wrapper.c -ldl $ LD_PRELOAD="./time_wrapper.so" ./hoge
なんか型変換を行っている部分が不安。
もし誰か見ていてバグに気づいたら教えてください。