我需要在代码中处理超时场景,如果系统支持Monotonic Clock,则需要使用clock_gettime(CLOCK_MONOTONIC)
。
#ifdef CLOCK_MONOTONIC
clock_gettime(CLOCK_MONOTONIC, & spec);
#else
clock_gettime(CLOCK_REALTIME, & spec);
#endif
我不确定这是否足够。也就是说,系统是否有可能通过它定义CLOCK_MONOTONIC
并不真正支持单调时钟?或者检查是否支持单调时钟的可靠方法是什么?
答案 0 :(得分:5)
根据POSIX的字母,即使定义了常量CLOCK_MONOTONIC
,您实际上也可能需要运行时测试。处理此问题的官方方法是使用_POSIX_MONOTONIC_CLOCK
“功能测试宏”,但这些宏的语义非常复杂:引用http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/unistd.h.html,
如果未定义符号常量或使用值-1定义符号常量,则编译不支持该选项。如果定义的值大于零,则在执行应用程序时应始终支持该选项。如果使用零值定义,则该选项应支持编译,并且可能在运行时支持或不支持。
将这种三向区分转换为代码会给你这样的东西:
#if !defined _POSIX_MONOTONIC_CLOCK || _POSIX_MONOTONIC_CLOCK < 0
clock_gettime(CLOCK_REALTIME, &spec);
#elif _POSIX_MONOTONIC_CLOCK > 0
clock_gettime(CLOCK_MONOTONIC, &spec);
#else
if (clock_gettime(CLOCK_MONOTONIC, &spec))
clock_gettime(CLOCK_REALTIME, &spec));
#endif
但如果你在定义CLOCK_MONOTONIC本身时总是进行运行时测试,它会更简单,更易读:
#ifdef CLOCK_MONOTONIC
if (clock_gettime(CLOCK_MONOTONIC, &spec))
#endif
clock_gettime(CLOCK_REALTIME, &spec);
这会在支持CLOCK_MONOTONIC
的当前操作系统上增加一些微不足道的代码,但在我看来,可读性的好处是值得的。
无条件使用CLOCK_MONOTONIC
也有很强的理由;你有可能找到一个根本不支持clock_gettime
的操作系统(例如MacOS X仍然没有它),而不是clock_gettime
而不是CLOCK_MONOTONIC
的操作系统{1}}。
答案 1 :(得分:1)
POSIX仅要求clientCertificateKeyStoreUrl=file:path_to_truststore_file
clientCertificateKeyStorePassword=mypassword
存在,其他时钟是可选的。
如果单调时钟可用,宏CLOCK_REALTIME
将在_POSIX_MONOTONIC_CLOCK
中定义(根据man page的可用性部分)
答案 2 :(得分:1)
如@ zwol的答案所示,事情真的有点复杂和有意义 -
请参阅以下简单程序(foo.c
):
#include <stdio.h>
#include <unistd.h>
#include <time.h>
int
main()
{
struct timespec spec;
printf("_POSIX_MONOTONIC_CLOCK = %d\n",
(int)_POSIX_MONOTONIC_CLOCK);
printf("sysconf(_SC_MONOTONIC_CLOCK) = %ld\n",
sysconf(_SC_MONOTONIC_CLOCK) );
printf("clock_gettime(CLOCK_MONOTONIC) = %d\n",
clock_gettime(CLOCK_MONOTONIC, & spec) );
return 0;
}
在Linux上(Debian 9,x86_64):
[STEP 101] # uname -a
Linux debian9 4.9.0-6-amd64 #1 SMP Debian 4.9.88-1 (2018-04-29) x86_64 GNU/Linux
[STEP 102] # gcc foo.c && ./a.out
_POSIX_MONOTONIC_CLOCK = 0
sysconf(_SC_MONOTONIC_CLOCK) = 200809
clock_gettime(CLOCK_MONOTONIC) = 0
[STEP 103] #
在macOS(10.13,High Sierra)上:
[STEP 201] $ uname -a
Darwin macbook.home 17.5.0 Darwin Kernel Version 17.5.0: Fri Apr 13 19:32:32 PDT 2018; root:xnu-4570.51.2~1/RELEASE_X86_64 x86_64
[STEP 202] $ cc foo.c && ./a.out
_POSIX_MONOTONIC_CLOCK = -1
sysconf(_SC_MONOTONIC_CLOCK) = -1
clock_gettime(CLOCK_MONOTONIC) = 0
[STEP 203] $
在FreeBSD上(11.1,x86_64):
[STEP 301] # uname -a
FreeBSD freebsd 11.1-RELEASE FreeBSD 11.1-RELEASE #0 r321309: Fri Jul 21 02:08:28 UTC 2017 root@releng2.nyi.freebsd.org:/usr/obj/usr/src/sys/GENERIC amd64
[STEP 302] # cc foo.c && ./a.out
_POSIX_MONOTONIC_CLOCK = 200112
sysconf(_SC_MONOTONIC_CLOCK) = 200112
clock_gettime(CLOCK_MONOTONIC) = 0
[STEP 303] #
macOS的结果让我很惊讶。 sysconf()
返回-1
但clock_gettime(CLOCK_MONOTONIC)
成功!不确定这是否表明macOS不符合POSIX标准。无论如何,它证明使用sysconf()
进行运行时检查是不可靠的!
最后我要谈到这个:
int
Clock_gettime(struct timespec * spec)
{
static bool firstime = true;
static clockid_t clock = CLOCK_REALTIME;
if (firstime) {
firstime = false;
#ifdef CLOCK_MONOTONIC
if (clock_gettime(CLOCK_MONOTONIC, spec) == 0) {
clock = CLOCK_MONOTONIC;
return 0;
}
#endif
}
return clock_gettime(clock, spec);
}