Howto

プログラム内から時間を取得・設定する方法

プログラム内から様々な種類のシステムクロックを取得・設定する方法を紹介します。ハードウェアクロックについては、Howto:リアルタイムクロックへの時刻の保存方法を参照してください。

1. さまざまな時間を取得・設定する方法

プログラム内から時間を取得・設定するAPIとして代表的なものに、gettimeofday()/settimeofday()がありますが
これらはすでに非推奨となっているため、現在推奨されているclock_gettime()/clock_settime()を使用します。
以下が現在の時間を取得するサンプルコードです。

#include <stdio.h>
#include <time.h>
int main(int argc, char *argv[])
{
    struct timespec ts;
    clock_gettime(CLOCK_REALTIME, &ts);
    printf("tv_sec = %ld, tv_nsec = %ld\n", ts.tv_sec, ts.tv_nsec);
 
    return 0;
}

clock_gettime()の第一引数を変えることでさまざまな時間を取得できます。
以下のような種類があります。

パラメータ 説明
CLOCK_REALTIME 現在のシステム時刻(いわゆる時計)。adjtime()1やNTPによる補正2、および手動での時間の変更の影響を受ける。
CLOCK_REALTIME_COARSE 高速に動作するが精度の低いCLOCK_REALTIME。
CLOCK_MONOTONIC ある時点3からの単調増加な経過時間。手動での時間変更の影響は受けないが、adjtime()やNTPによる段階的な補正の影響は受ける。取得のみで設定することは不可。
CLOCK_MONOTONIC_COARSE 高速に動作するが精度の低いCLOCK_MONOTONIC。
CLOCK_MONOTONIC_RAW adjtime()やNTPによる補正の影響も受けないCLOCK_MONOTONIC。
CLOCK_BOOTTIME システムがサスペンドしている時間も含まれるCLOCK_MONOTONIC。
CLOCK_PROCESS_CPUTIME_ID このプロセスで消費されたCPU時間。
CLOCK_THREAD_CPUTIME_ID スレッド単位での消費されたCPU時間。

用途に合わせてパラメータを選択する
以下に用途別のパラメータの例を挙げます。

用途の例 パラメータ
現在時刻を取得したい CLOCK_REALTIME
プログラム内で周期的な処理を行いたい CLOCK_MONOTONIC4 常に増加することが保証されているので補正の影響で時間がもどったりはしません。
プログラムのCPU時間を計測したい CLOCK_PROCESS_CPUTIME_ID sleep()などで止まっている間は時間は増えません。
スレッド単位でのCPU時間を計測したい CLOCK_THREAD_CPUTIME_ID

2. 時間の精度

精度はclock_getres()で取得できます。

#include <stdio.h>
#include <time.h>
int main(int argc, char *argv[])
{
    struct timespec ts;
    clock_getres(CLOCK_REALTIME, &ts);
    printf("tv_sec = %ld, tv_nsec = %ld\n", ts.tv_sec, ts.tv_nsec);
 
    return 0;
}

また、以下のコマンドでも確認できます。

[armadillo ~]# cat /proc/timer_list | grep resolution
  .resolution: 1 nsecs                                                          
  .resolution: 1 nsecs                                                          
  .resolution: 1 nsecs                                                          
  .resolution: 1 nsecs  

  1. システム時間を少しずつ調整するAPIです ↩︎

  2. 少しずつ調整するslewモードと一気に調整するstepモードがあります ↩︎

  3. 通常はシステム起動時点 ↩︎

  4. CLOCK_MONOTONIC_ROWは短時間ならばよいですが、長時間の場合は不正確になる場合があります。 ↩︎