clock_getres

Section: System Calls (2)
Updated: 2026-03-07
Index JM Home Page roff page
 

名前

clock_getres, clock_gettime, clock_settime - クロックと時間の関数  

ライブラリ

glibc 2.17 から標準 C ライブラリ (libc,\ -lc)

glibc 2.17 より前は、Real-time library (librt,\ -lrt)  

書式

#include <time.h>

int clock_getres(clockid_t clockid, struct timespec *_Nullable res);

int clock_gettime(clockid_t clockid, struct timespec *tp);
int clock_settime(clockid_t clockid, const struct timespec *tp);

glibc 向けの機能検査マクロの要件 (feature_test_macros(7) 参照):

clock_getres(), clock_gettime(), clock_settime():

    _POSIX_C_SOURCE >= 199309L
 

説明

関数 clock_getres() は 指定されたクロック clockid の分解能 (精度) を探し出します。res が NULL でない場合、その分解能を res で指される struct timespec に格納します。クロックの分解能は実装に依存し、 特定のプロセスによって設定することはできません。clock_settime() の引数 tp で指される時間の値が res の倍数でない場合、 res の倍数に切り詰められます。

関数 clock_gettime() と clock_settime() は、指定されたクロック clockid の時間を取得または設定します。

restp 引数は timespec(3) 構造体です。

clockid 引数は特定のクロックの識別子であり、そのクロックで動作します。クロックはシステム全体に適用することもでき、その場合は全てのプロセスから見ることができます。また 1 つのプロセス内でのみ時間を計測する場合は、 プロセス毎に適用することもできます。

全ての実装においてシステム全体のリアルタイムクロックがサポートされ、 CLOCK_REALTIME で識別されます。時間は紀元 (the Epoch) からの秒とナノ秒で表されます。時間が変更された場合、相対的な時間間隔のタイマーは影響を受けませんが、絶対的な時点のタイマーは影響を受けます。

さらにいくつかのクロックが実装されているかもしれません。対応する時間の値を解釈する方法とタイマーへの影響は、定められていません。

glibc と Linux カーネルの最新のバージョンでは、以下のクロックがサポートされています。

CLOCK_REALTIME
実際の(つまり、壁時計)時間を測定する設定可能なシステム全体の時計。この時計を設定するには、適切な権限が必要です。この時計は、システム時間の不連続なジャンプ(たとえば、システム管理者が手動で時計を変更した場合)、および adjtime(3)、adjtimex(2)、clock_adjtime(2)、および ntp_adjtime(3) を介して NTP および同様のアプリケーションによって実行される周波数調整の影響を受けます。この時計は通常、うるう秒を無視することを除いて、1970-01-01 00:00:00協定世界時(UTC) からの秒数をカウントします。うるう秒付近では、通常、UTC とほぼ同期するように NTP によって調整されます。
CLOCK_REALTIME_ALARM (Linux 3.0 以降; Linux 固有)
CLOCK_REALTIME と似ていますが、CLOCK_REALTIME を設定することで間接的にのみ設定可能であり、システムがサスペンドされている場合は異なる動作をします。timer_create(2)を参照。
CLOCK_REALTIME_COARSE (Linux 2.6.32 以降; Linux 特有)
CLOCK_REALTIME の高速で精度の低いバージョンです。CLOCK_REALTIME を設定することによって間接的にのみ設定できます。非常に高速ですが、きめ細かなタイムスタンプが必要ない場合に使用します。アーキテクチャごとのサポートが必要であり、おそらく vdso(7) のこのフラグのアーキテクチャサポートも必要です。
CLOCK_TAI (Linux 3.10 以降; Linux 固有)
壁時計から得たシステム全体の時計で、閏秒をカウントします。この時計は、CLOCK_REALTIME のように閏秒を挿入することによる時計調整を受けません。1970-01-01 00:00 TAI(1969-12-31 23:59:50 UTC) から秒をカウントするので、そのエポックは CLOCK_REALTIME の 10秒前になります。しかし、その実装は NTP からのヘルプを必要とし、そのヘルプが利用できない場合は、代わりに CLOCK_REALTIME のように動作します。
1972 年より前のタイムスタンプに対する CLOCK_REALTIME との関係は、閏秒が 1972-01-01 に導入されたので、近似的なものに過ぎません。閏秒は廃止される予定なので、これからの値は何年もの間 CLOCK_REALTIME より正確に 37秒大きいままになり、その後は CLOCK_REALTIME からのオフセットは、まだ指定されていない他のメカニズムによって調整される可能性があります。これは、CLOCK_REALTIME を設定することによって間接的にのみ設定できます。
頭字語 TAI は、フランス語の "temps atomique international"、または国際原子時を表します。
CLOCK_MONOTONIC
POSIXの "過去のある特定されていない時点"で記述されているように、以降の単調時間を表す設定不可能なシステム全体のクロック。Linux では、この時点はシステムがブートされてから動作している秒数に対応します。
CLOCK_MONOTONIC クロックは、システム時間の不連続なジャンプ(たとえば、システム管理者が手動でクロックを変更した場合)の影響を受けませんが、周波数調整の影響を受けます。このクロックは、システムが一時停止されている時間はカウントしません。すべての CLOCK_MONOTONIC バリアントは、連続した呼び出しによって返される時間が逆方向にならないことを保証しますが、連続した呼び出しは、アーキテクチャに依存して同一の(増加しない)時間値を返す場合があります。
CLOCK_MONOTONIC_COARSE (Linux 2.6.32 以降; Linux 特有)
CLOCK_MONOTONIC の高速だが精度の低いバージョン。非常に高速ですが、きめの細かいタイムスタンプが必要ない場合に使用します。アーキテクチャごとのサポートが必要であり、おそらく vdso(7) 内での、このフラグのアーキテクチャサポートも必要です。
CLOCK_MONOTONIC_RAW (Linux 2.6.28 以降; Linux 特有)
CLOCK_MONOTONIC に似ていますが、周波数調整の対象ではないハードウェアベースの時間にアクセスできます。このクロックは、システムがサスペンドされている時間をカウントしません。
CLOCK_BOOTTIME (Linux 2.6.39 以降; Linux 固有)
システム全体で設定できないクロックで、CLOCK_MONOTONIC と同じです。ただし、システムがサスペンドされている時間も含まれます。これにより、アプリケーションは、settimeofday(2) などを使用して時間が変更された場合に不連続になる可能性がある CLOCK_REALTIME の複雑な問題に対処することなく、サスペンド対応の単調クロックを取得できます。
CLOCK_BOOTTIME_ALARM (Linux 3.0 以降; Linux 固有)
CLOCK_BOOTTIME と同様ですが、システムがサスペンドされている場合は異なる動作をします。
CLOCK_PROCESS_CPUTIME_ID (Linux 2.6.12 以降)
このクロックは、このプロセスによって消費された CPU 時間を測定します(つまり、プロセス内のすべてのスレッドによって消費された CPU 時間)。Linuxでは、このクロックは設定できません。
CLOCK_THREAD_CPUTIME_ID (Linux 2.6.12 以降)
このクロックは、このスレッドによって消費される CPU 時間を測定します。Linux では、このクロックは設定できません。

Linuxは、以下に述べるように、動的なクロックインスタンスも実装しています。  

動的クロック

上記のハードコードされた System-V スタイルのクロック ID に加えて、Linux は特定のキャラクタデバイス上での POSIX クロック操作もサポートしています。このようなデバイスは "ダイナミック" クロックと呼ばれ、Linux 2.6.39 からサポートされています。

適切なマクロを使用すると、開いているファイル記述子をクロック ID に変換して、clock_gettime()、clock_settime()、および clock_adjtime(2) に渡すことができます。次の例は、ファイル記述子を動的クロック ID に変換する方法を示しています。

#define CLOCKFD 3
#define FD_TO_CLOCKID(fd)   ((~(clockid_t) (fd) << 3) | CLOCKFD)
#define CLOCKID_TO_FD(clk)  ((unsigned int) ~((clk) >> 3))

struct timespec ts;
clockid_t clkid;
int fd;

fd = open("/dev/ptp0", O_RDWR);
clkid = FD_TO_CLOCKID(fd);
clock_gettime(clkid, &ts);
 

返り値

clock_gettime(), clock_settime(), clock_getres() は成功した場合に 0 を返し、失敗した場合に -1 を返し、エラーを示すために errno が設定されます。  

エラー

EACCES
指示されたクロックを設定する権限が clock_settime() にありません。
EFAULT
tp がアクセス可能なアドレス空間の外を指しました。
EINVAL
指定された clockid は2つの理由のいずれかで無効です。System-V 形式のハードコードされた正の値が範囲外であるか、または動的クロック ID がクロックオブジェクトの有効なインスタンスを参照していません。
EINVAL
これは (clock_settime()):tp.tv_secが負であるか、tp.tv_nsecが[0, 999,999,999]の範囲外です。
EINVAL
これは clock_settime() の呼び出しで指定された clockid は、設定可能なクロックではありません。
EINVAL (Linux 4.3 以降)
これは clockidCLOCK_REALTIMEclock_settime() への呼び出しで、時間を CLOCK_MONOTONIC クロックの現在の値より小さい値に設定しようとしました。

 ENODEV
動的な clk_id で表現されるホットプラグ可能なデバイス(例えば USB のような)は、そのキャラクタデバイスがオープンされた後に消滅します。

 ENOTSUP
この操作は、指定された動的 POSIX クロックデバイスではサポートされていません。
EOVERFLOW
タイムスタンプが time_tの範囲に収まりません。これは、時刻が 2038-01-19 03:14:08 UTC 以降の場合に、32 ビット time_t の実行ファイルを 64 ビットカーネルで実行すると発生する可能性があります。ただし、他の状況でシステム時刻が time_t の範囲外にある場合、動作は未定義です。
EPERM
指示されたクロックを設定する権限が clock_settime() にありません。
 

属性

この節で使用されている用語の説明については、 attributes(7) を参照してください。
インターフェース属性
clock_getres(), clock_gettime(), clock_settime() Thread safetyMT-Safe
 

バージョン

POSIX.1 の規定は以下のとおりです:

clock_settime() を使用して CLOCK_REALTIME クロックの値を設定しても、nanosleep() 関数を含む、このクロックに基づく相対タイムサービスを待機しているブロックされたスレッドには影響しません。また、このクロックに基づく相対タイマーの期限切れにも影響しません。したがって、これらのタイムサービスは、クロックの新しい値または古い値に関係なく、要求された相対間隔が経過すると期限切れになります。

POSIX.1-2001 では、 「適切な特権 (appropriate privileges)」を持ったプロセスは、 clock_settime() を使って、クロック CLOCK_PROCESS_CPUTIME_IDCLOCK_THREAD_CPUTIME_ID を設定することができるとされています。 Linux では、これらのクロックは設定できません(すなわち、どのプロセスも「適切な特権」を持ちません)。  

C ライブラリ/kernel の違い

いくつかのアーキテクチャでは、clock_gettime()の実装は vdso(7)で提供されます。  

標準

POSIX.1-2024.  

履歴

POSIX.1-1996, Linux 2.6.

これらの関数が利用可能な POSIX システムでは、シンボル _POSIX_TIMERS<unistd.h> で 0 より大きい値に定義されています。POSIX.1-2008 はこれらの関数を必須としています。

シンボル _POSIX_MONOTONIC_CLOCK,_POSIX_CPUTIME,_POSIX_THREAD_CPUTIME は、CLOCK_MONOTONIC,CLOCK_PROCESS_CPUTIME_ID,CLOCK_THREAD_CPUTIME_ID が利用可能であることを示します(sysconf(3) も参照)。

POSIX.1-2024 では CLOCK_MONOTONIC が必須になりました。  

SMP システムに関する歴史的な注意事項

Linux が CLOCK_PROCESS_CPUTIME_IDCLOCK_THREAD_CPUTIME_ID クロックのカーネルによるサポートを追加する前は、 glibc はこれらのクロックは多くのプラットフォームで CPU のタイマレジスタ (i386 上の TSC、Itanium 上の AR.ITC) を用いて実現されていました。これらのレジスタは CPU 間で異なる可能性があり、 プロセスが他の CPU に移動させられた場合、 結果としてこれらのクロックが 偽の結果 (bogus results) を返すかもしれません。

SMP システムの各 CPU が別々のクロック源を持つ場合、 タイマレジスタ間の相互関係を管理する方法はありません。これは各 CPU が微妙に異なる周波数で動作するためです。これが真実の場合 (訳註: 各 CPU が別々のクロック源を持つ場合)、 clock_getcpuclockid(0)ENOENT を返して、その状況を表します。 2 つのクロックは、プロセスが特定の CPU 上に留まっていることが 保証できる場合にのみ有効です。

SMPシステムのプロセッサはすべてが正確に同時に起動するわけではないので、タイマレジスタは通常あるオフセットで動作しています。アーキテクチャによっては、起動時にこれらのオフセットを制限しようとするコードが含まれています。しかし、コードはオフセットを正確に調整することを保証できません。glibc には(Linux カーネルとは異なり)これらのオフセットを扱う規定はありません。通常、これらのオフセットは小さいので、ほとんどの場合、その影響は無視できます。

glibc 2.4 以降では、 このページで説明したシステムコールのラッパー関数は、 CLOCK_PROCESS_CPUTIME_IDCLOCK_THREAD_CPUTIME_ID のカーネル実装が利用できるシステム (すなわち Linux 2.6.12 以降) ではカーネル実装を利用することで、 上述の問題を回避しています。  

以下のプログラムは、clock_gettime() と clock_getres() をさまざまなクロックで使用する方法を示しています。以下は、プログラムを実行したときに表示される例です:

$ ./clock_times x;
CLOCK_REALTIME : 1585985459.446 (18356 days +  7h 30m 59s)
     resolution:          0.000000001
CLOCK_TAI      : 1585985496.447 (18356 days +  7h 31m 36s)
     resolution:          0.000000001
CLOCK_MONOTONIC:      52395.722 (14h 33m 15s)
     resolution:          0.000000001
CLOCK_BOOTTIME :      72691.019 (20h 11m 31s)
     resolution:          0.000000001
 

プログラムのソース

/* clock_times.c

   Licensed under GNU General Public License v2 or later.
*/
#define _XOPEN_SOURCE 600
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <time.h>

#define SECS_IN_DAY (24 * 60 * 60)

static void
displayClock(clockid_t clock, const char *name, bool showRes)
{
    long             days;
    struct timespec  ts;

    if (clock_gettime(clock, &ts) == -1) {
        perror("clock_gettime");
        exit(EXIT_FAILURE);
    }

    printf("%-15s: %10jd.%03ld (", name,
           (intmax_t) ts.tv_sec, ts.tv_nsec / 1000000);

    days = ts.tv_sec / SECS_IN_DAY;
    if (days > 0)
        printf("%ld days + ", days);

    printf("%2dh %2dm %2ds",
           (int) (ts.tv_sec % SECS_IN_DAY) / 3600,
           (int) (ts.tv_sec % 3600) / 60,
           (int) ts.tv_sec % 60);
    printf(")\n");

    if (clock_getres(clock, &ts) == -1) {
        perror("clock_getres");
        exit(EXIT_FAILURE);
    }

    if (showRes)
        printf("     resolution: %10jd.%09ld\n",
               (intmax_t) ts.tv_sec, ts.tv_nsec);
}

int
main(int argc, char *[])
{
    bool showRes = argc > 1;

    displayClock(CLOCK_REALTIME, "CLOCK_REALTIME", showRes);
#ifdef CLOCK_TAI
    displayClock(CLOCK_TAI, "CLOCK_TAI", showRes);
#endif
    displayClock(CLOCK_MONOTONIC, "CLOCK_MONOTONIC", showRes);
#ifdef CLOCK_BOOTTIME
    displayClock(CLOCK_BOOTTIME, "CLOCK_BOOTTIME", showRes);
#endif
    exit(EXIT_SUCCESS);
}
 

関連項目

date(1), gettimeofday(2), settimeofday(2), time(2), adjtime(3), clock_getcpuclockid(3), ctime(3), ftime(3), pthread_getcpuclockid(3), sysconf(3), timespec(3), time(7), time_namespaces(7), vdso(7), hwclock(8)


 

Index

名前
ライブラリ
書式
説明
動的クロック
返り値
エラー
属性
バージョン
C ライブラリ/kernel の違い
標準
履歴
SMP システムに関する歴史的な注意事項
プログラムのソース
関連項目

This document was created by man2html, using the manual pages.