考虑以下完全符合 POSIX 标准的源代码:
#include <stdio.h>
#include <limits.h>
#include <stdint.h>
#include <stdlib.h>
#include <pthread.h>
#include <sys/time.h>
int main (int argc, char ** argv) {
pthread_cond_t c;
pthread_mutex_t m;
char printTime[UCHAR_MAX];
pthread_mutex_init(&m, NULL);
pthread_cond_init(&c, NULL);
for (;;) {
struct tm * tm;
struct timeval tv;
struct timespec ts;
gettimeofday(&tv, NULL);
printf("sleep (%ld)\n", (long)tv.tv_sec);
sleep(3);
tm = gmtime(&tv.tv_sec);
strftime(printTime, UCHAR_MAX, "%Y-%m-%d %H:%M:%S", tm);
printf("%s (%ld)\n", printTime, (long)tv.tv_sec);
ts.tv_sec = tv.tv_sec + 5;
ts.tv_nsec = tv.tv_usec * 1000;
pthread_mutex_lock(&m);
pthread_cond_timedwait(&c, &m, &ts);
pthread_mutex_unlock(&m);
}
return 0;
}
每 5 秒打印一次当前系统日期,但是,在获取当前系统时间之间会睡眠 3 秒(gettimeofday
)和条件等待(pthread_cond_timedwait
).
在打印“sleep (...)”之后,尝试将系统时钟设置为过去两天。会发生什么?好吧,不是像通常那样在条件下再等待 2 秒,pthread_cond_timedwait
现在等待two days和2秒。
我该如何解决这个问题?
如何编写 POSIX 兼容的代码,使其在用户操作系统时钟时不会中断?
请记住,即使没有用户交互,系统时钟也可能会发生变化(例如,NTP 客户端可能每天自动更新一次时钟)。将时钟设置为未来是没有问题的,它只会导致睡眠提早醒来,这通常没有问题,您可以轻松地“检测”并进行相应处理,但是将时钟设置为过去(例如,因为它是将来运行时(NTP 检测到并修复它)可能会导致大问题。
PS:
两者都不pthread_condattr_setclock()
nor CLOCK_MONOTONIC
存在于我的系统上。这些对于 POSIX 2008 规范(“Base”的一部分)来说是强制性的,但大多数系统迄今为止仍然只遵循 POSIX 2004 规范,并且在 POSIX 2004 规范中,这两个是可选的(高级实时扩展)。