【发布时间】:2015-09-13 10:50:15
【问题描述】:
大多数 POSIX 兼容系统都提供了获取或设置高分辨率计时器的功能:
int clock_gettime(clockid_t clock_id, struct timespec *tp);
每个系统的文档通常列出几个符号名称作为可能的clock_id 值,但从未提及实际数值。事实证明,不仅不同系统的数值不同,而且相同含义的符号名称也不相同。更重要的是,并非系统实际支持的所有时钟都在 time.h (bits/time.h) 中定义 — 有些只定义在,比方说, linux/time.h.
也就是说,在Linux系统中我们可能有:
#define CLOCK_REALTIME 0
#define CLOCK_MONOTONIC 1
#define CLOCK_PROCESS_CPUTIME_ID 2
#define CLOCK_THREAD_CPUTIME_ID 3
#define CLOCK_MONOTONIC_RAW 4
#define CLOCK_REALTIME_COARSE 5
#define CLOCK_MONOTONIC_COARSE 6
#define CLOCK_BOOTTIME 7
#define CLOCK_REALTIME_ALARM 8
#define CLOCK_BOOTTIME_ALARM 9
#define CLOCK_SGI_CYCLE 10 // In linux/time.h only.
#define CLOCK_TAI 11 // In linux/time.h only.
在 Cygwin 环境中(不是逐字摘录):
#define CLOCK_REALTIME 1 // Means CLOCK_MONOTONIC?
#define CLOCK_MONOTONIC 4 // Means CLOCK_MONOTONIC_RAW?
#define CLOCK_PROCESS_CPUTIME_ID 2
#define CLOCK_THREAD_CPUTIME_ID 3
在 FreeBSD 中:
#define CLOCK_REALTIME 0
#define CLOCK_VIRTUAL 1
#define CLOCK_PROF 2
#define CLOCK_MONOTONIC 4
#define CLOCK_UPTIME 5 // Synonymous to CLOCK_BOOTTIME?
#define CLOCK_UPTIME_PRECISE 7
#define CLOCK_UPTIME_FAST 8
#define CLOCK_REALTIME_PRECISE 9 // Same as CLOCK_REALTIME?
#define CLOCK_REALTIME_FAST 10 // Synonymous to CLOCK_REALTIME_COARSE?
#define CLOCK_MONOTONIC_PRECISE 11 // Same as CLOCK_MONOTONIC?
#define CLOCK_MONOTONIC_FAST 12 // Synonymous to CLOCK_MONOTONIC_COARSE?
#define CLOCK_SECOND 13
#define CLOCK_THREAD_CPUTIME_ID 14
#define CLOCK_PROCESS_CPUTIME_ID 15
在 AIX 中:
#define CLOCK_REALTIME ...
#define CLOCK_MONOTONIC ...
#define CLOCK_PROCESS_CPUTIME_ID ...
#define CLOCK_THREAD_CPUTIME_ID ...
在 SunOS 中:
#define CLOCK_REALTIME ...
#define CLOCK_HIGHRES ... // Synonymous to CLOCK_MONOTONIC_RAW?
在 QNX 中:
#define CLOCK_REALTIME ...
#define CLOCK_SOFTTIME ...
#define CLOCK_MONOTONIC ...
等等。
这让我想知道如何以可移植的方式将clock_gettime() 与CLOCK_REALTIME 以外的第一个参数一起使用。例如,如果我想使用CLOCK_MONOTONIC_COARSE 或CLOCK_BOOTTIME,我怎么知道BSD 分别称它们为CLOCK_MONOTONIC_FAST 和CLOCK_UPTIME?
根据前 4 个符号名称的数值做出假设是否明智?如:
#define POSIX_CLOCK_REALTIME 0
#define POSIX_CLOCK_MONOTONIC 1
#define POSIX_CLOCK_PROCESS_CPUTIME_ID 2
#define POSIX_CLOCK_THREAD_CPUTIME_ID 3
#define POSIX_CLOCK_MONOTONIC_RAW 4
#if CLOCK_REALTIME == POSIX_CLOCK_MONOTONIC
#warning This platform has monotonic realtime clock.
#end if
#if CLOCK_MONOTONIC == POSIX_CLOCK_MONOTONIC_RAW
#warning This platform has undisciplined monotonic clock.
#end if
如果一个系统实际上支持CLOCK_TAI,但没有在time.h中定义它,我该如何检查和使用它,考虑到相同的数值11可能代表@987654337 @ 或其他系统中的任何内容?
【问题讨论】:
-
不,做假设是不安全的。首先,您需要研究目标系统上的每个时钟,看看哪些时钟与另一个时钟匹配。那么您可能应该使用条件编译(例如
#ifdef __linux__)为您的应用程序选择正确的时钟。 -
@JoachimPileborg 在看到所有这些差异之后,我现在担心即使是
#ifdef __linux__方法对于所有具有不同程度的定制和私有扩展的基于 Linux 的系统(由那些我的意思是经过大量修改的系统,而不仅仅是重新命名和重新设计的发行版)。 -
如果系统没有在time.h中定义
CLOCK_TAI,你怎么知道它是否真的支持? -
@SteveSummit 运行时检查是可能的,因为
clock_gettime如果时钟受支持且当前可用(具有有效值)返回零,否则返回非零。如果所有系统的数值都相同,那么定义自己的常量就足够了,不依赖于系统提供的包含文件(往往会不同步)并避免命名不一致。但是,不幸的是,数值是模棱两可的。
标签: c time posix portability time.h