我用c++编写了一个框架dll,它可以在windows、Mac、Android、IOS等跨平台上使用。我需要实现一个 API get_time_since_boot_milli_seconds() ,它将为我提供自系统跨平台(windows / mac / IOS / Android)启动以来的毫秒时间。
我找到了像 GetTickCount64() 这样的函数,但它只能在 Windows 中使用。同样,有些功能仅适用于 Mac。我尝试过 std::chrono ,但没有得到任何相关的API。
我期望标准的 std C++ 函数可以在每个平台上启动后给我以毫秒为单位的时间。
我认为标准计时器都不能提供正常运行时间保证。所以是的,你必须自己做。
Windows:
#if (_WIN32_WINNT >= 0x0600)
uint64_t uptime_milli = GetTickCount64();
#else
uint32_t uptime_milli = GetTickCount();
#endif
上述解决方案应包括睡眠/挂起和休眠时间。 根据您支持的操作系统版本范围,您可能需要将编译时
#if
替换为运行时测试 GetTickCount64
是否在“kernel32.dll”中可用。
替代解决方案是使用
QueryUnbiasedInterruptTime()
。它不包括睡眠/挂起/休眠时间,但它更可靠(从某种意义上说,用户不能作弊和干扰)。
较新的基于 Posix 的平台(自 Linux 2.6.39 起):
struct timespec up;
int err = clock_gettime(CLOCK_BOOTTIME, &up);
if (err != 0)
HandleError();
uint64_t uptime_nano = up.tv_sec * 1000000000 + up.tv_nsec;
此函数返回的间隔应包含睡眠和挂起时间。
较旧的Linux(glibc 2.3.6 左右,无法检查以确保):
struct timespec up;
int err = clock_gettime(CLOCK_MONOTONIC, &up);
if (err != 0)
HandleError();
uint64_t uptime_nano = up.tv_sec * 1000000000 + up.tv_nsec;
此方法返回的时间不包括睡眠/挂起状态。
OS X、旧版 FreeBSD、Linux 和 Android:
struct timeval boot;
int mib[] = { CTL_KERN, KERN_BOOTTIME };
size_t size = sizeof(boot);
int err = sysctl(mib, 2, &boot, &size, 0, 0);
if (err != 0)
HandleError();
struct timeval now;
err = gettimeofday(&now, 0);
if (err != 0)
HandleError();
uint64_t uptime_micro = (now.tv_sec * 1000000 + now.tv_usec) - (boot.tv_sec * 1000000 + boot.tv_usec);
此方法存在竞争,只要计算需要两次调用即可。
Mac 还提供
mach_absolute_time()
功能,但其行为可能会出乎意料:它会计算前 30 秒的睡眠时间,然后停止计数。