据我了解,Linux 的起点CLOCK_MONOTONIC
是启动时间。在我目前的工作中,我更喜欢使用单调时钟而不是CLOCK_REALTIME
(用于计算),但同时我需要在报告中提供人性化的时间戳(带有年/月/日)。它们可能不是很精确,所以我想在启动时间加入单调计数器。
我可以从哪里使用 api 调用在 linux 系统上获得这个时间?
假设 Linux 内核在开始跟踪单调时钟的同时启动正常运行时间计数器,您可以通过从当前时间减去正常运行时间来得出启动时间(相对于 Epoch) 。
Linux通过该结构以秒为单位提供系统正常运行时间;可以通过该函数在符合 POSIX 的库上获取自 Epoch 以来sysinfo
的当前时间(以秒为单位)。time
#include <stddef.h>
#include <stdio.h>
#include <time.h>
#include <sys/sysinfo.h>
int main(void) {
/* get uptime in seconds */
struct sysinfo info;
sysinfo(&info);
/* calculate boot time in seconds since the Epoch */
const time_t boottime = time(NULL) - info.uptime;
/* get monotonic clock time */
struct timespec monotime;
clock_gettime(CLOCK_MONOTONIC, &monotime);
/* calculate current time in seconds since the Epoch */
time_t curtime = boottime + monotime.tv_sec;
/* get realtime clock time for comparison */
struct timespec realtime;
clock_gettime(CLOCK_REALTIME, &realtime);
printf("Boot time = %s", ctime(&boottime));
printf("Current time = %s", ctime(&curtime));
printf("Real Time = %s", ctime(&realtime.tv_sec));
return 0;
}
不幸的是,单调时钟可能与启动时间不完全匹配。当我在我的机器上测试上述代码时,单调时钟与系统正常运行时间相差一秒。但是,只要考虑到相应的偏移量,您仍然可以使用单调时钟。
可移植性注意事项:尽管 Linux 可能会返回相对于引导时间的当前单调时间,但通常允许 POSIX 机器从任意(但一致)时间点(通常是 Epoch)返回当前单调时间。
作为旁注,您可能不需要像我一样推导出启动时间。我怀疑有一种方法可以通过 Linux API 获取启动时间,因为有许多 Linux 实用程序以人类可读的格式显示启动时间。例如:
$ who -b
system boot 2013-06-21 12:56
我找不到这样的调用,但检查其中一些常用实用程序的源代码可能会揭示它们如何确定人类可读的启动时间。
对于该who
实用程序,我怀疑它利用该utmp
文件来获取系统启动时间。
http://www.kernel.org/doc/man-pages/online/pages/man2/clock_getres.2.html:
CLOCK_MONOTONIC Clock that cannot be set and represents monotonic time since some unspecified starting point.
意味着您可以CLOCK_MONOTONIC
用于区间计算和其他事情,但您不能真正将其转换为人类可读的表示。
此外,您可能想要CLOCK_MONOTONIC_RAW
而不是CLOCK_MONOTONIC
:
CLOCK_MONOTONIC_RAW (since Linux 2.6.28; Linux-specific) Similar to CLOCK_MONOTONIC, but provides access to a raw hard‐ ware-based time that is not subject to NTP adjustments.
继续使用CLOCK_REALTIME
人类可读的时间。
CLOCK_MONOTONIC
通常不受系统时间任何调整的影响。例如,如果系统时钟是通过 NTP 调整的,CLOCK_MONOTONIC
则无法知道(也不需要)。
因此,CLOCK_MONOTONIC
如果您需要人类可读的时间戳,请不要使用。