如何将CLOCK_BOOTTIME时间戳转为CLOCK_REALTIME?是否有现成C库函数?
问题:内核启动时间戳转实时时间的现成C库函数?
我编写了一个类,通过PF_NETLINK套接字监听进程事件。调用recv()获取的消息中包含内核上次启动以来的纳秒级时间戳,需要将其转换为实时时间。目前我想到的方法是用clock_gettime()分别获取CLOCK_REALTIME和CLOCK_BOOTTIME的值计算偏移量,伪代码如下:
struct timespec realtime; struct timespec boottime; clock_gettime(CLOCK_REALTIME, &realtime); clock_gettime(CLOCK_BOOTTIME, &boottime); // 伪代码:结构体加减需要手动实现 struct timespec offset = realtime - boottime; struct timespec event_timestamp = ...; // 来自PF_NETLINK事件的时间戳 struct timespec event_realtime = event_timestamp + offset;
但该实现较为繁琐,想问是否有现成的C库函数完成此转换?
回答
没有现成的标准C库函数可以直接完成这个转换。
Linux下,将基于CLOCK_BOOTTIME的内核启动时间戳转换为CLOCK_REALTIME实时时间的核心逻辑,就是你思路中的计算两个时钟的偏移量——因为两者的时间差在系统运行期间(除非手动修改系统时间或NTP同步调整)是相对稳定的。
如果你需要简化实现,可以封装一个专用函数,手动完成timespec结构体的加减操作,示例代码如下:
#include <time.h> #include <errno.h> // 计算timespec差值:result = a - b static void timespec_sub(struct timespec *result, const struct timespec *a, const struct timespec *b) { result->tv_sec = a->tv_sec - b->tv_sec; result->tv_nsec = a->tv_nsec - b->tv_nsec; if (result->tv_nsec < 0) { result->tv_sec--; result->tv_nsec += 1000000000; } } // 计算timespec和:result = a + b static void timespec_add(struct timespec *result, const struct timespec *a, const struct timespec *b) { result->tv_sec = a->tv_sec + b->tv_sec; result->tv_nsec = a->tv_nsec + b->tv_nsec; if (result->tv_nsec >= 1000000000) { result->tv_sec++; result->tv_nsec -= 1000000000; } } // 将内核启动时间戳转换为实时时间 int boottime_timestamp_to_realtime(const struct timespec *boottime_ts, struct timespec *realtime_ts) { struct timespec current_realtime, current_boottime, offset; if (clock_gettime(CLOCK_REALTIME, ¤t_realtime) == -1) { return errno; } if (clock_gettime(CLOCK_BOOTTIME, ¤t_boottime) == -1) { return errno; } timespec_sub(&offset, ¤t_realtime, ¤t_boottime); timespec_add(realtime_ts, boottime_ts, &offset); return 0; }
注意:如果系统时间被手动修改或通过NTP同步调整,CLOCK_REALTIME和CLOCK_BOOTTIME的偏移量会发生变化,因此每次转换前都应该重新计算偏移量,不要缓存偏移值长期使用。
内容的提问来源于stack exchange,提问作者Alexis Wilke
相关产品推荐
相关产品推荐

