如何在c ++中以毫秒为单位获得系统启动时间?

时间:2015-05-07 08:15:35

标签: c++ time ctime

自系统启动以来,如何获得系统启动时间?我所发现的只是时代以来的时间,没有别的。

例如,像ctime库中的time(),但它只给我一个自纪元以来秒的值。我想要像time()这样的东西,但是从系统开始。

3 个答案:

答案 0 :(得分:22)

它依赖于操作系统,已经在stackoverflow上为多个系统提供了答案。

#include<chrono> // for all examples :)

Windows ...

使用GetTickCount64()(分辨率通常为10-16毫秒)

#include <windows>
// ...
auto uptime = std::chrono::milliseconds(GetTickCount64());

Linux ...

...使用/proc/uptime

#include <fstream>
// ...
std::chrono::milliseconds uptime(0u);
double uptime_seconds;
if (std::ifstream("/proc/uptime", std::ios::in) >> uptime_seconds)
{
  uptime = std::chrono::milliseconds(
    static_cast<unsigned long long>(uptime_seconds)*1000ULL
  );
}

...使用sysinfo(分辨率1秒)

#include <sys/sysinfo.h>
// ...
std::chrono::milliseconds uptime(0u);
struct sysinfo x;
if (sysinfo(&x) == 0)
{
  uptime = std::chrono::milliseconds(
    static_cast<unsigned long long>(x.uptime)*1000ULL
  );
}

OS X ...

...使用sysctl

#include <time.h>
#include <errno.h>
#include <sys/sysctl.h>
// ...
std::chrono::milliseconds uptime(0u);
struct timeval ts;
std::size_t len = sizeof(ts);
int mib[2] = { CTL_KERN, KERN_BOOTTIME };
if (sysctl(mib, 2, &ts, &len, NULL, 0) == 0)
{
  uptime = std::chrono::milliseconds(
    static_cast<unsigned long long>(ts.tv_sec)*1000ULL + 
    static_cast<unsigned long long>(ts.tv_usec)/1000ULL
  );
}

类似BSD的系统(或分别支持CLOCK_UPTIMECLOCK_UPTIME_PRECISE的系统)......

...使用clock_gettime(分辨率见clock_getres

#include <time.h>
// ... 
std::chrono::milliseconds uptime(0u);
struct timespec ts;
if (clock_gettime(CLOCK_UPTIME_PRECISE, &ts) == 0)
{
  uptime = std::chrono::milliseconds(
    static_cast<unsigned long long>(ts.tv_sec)*1000ULL + 
    static_cast<unsigned long long>(ts.tv_nsec)/1000000ULL
   );
}

答案 1 :(得分:3)

+1接受的答案。不错的调查。但OS X答案不正确,我想在这里显示更正。

OS X上输入sysctl的{​​{1}}函数返回系统引导的Unix Time,而不是引导后的时间。在此系统(以及其他所有系统)上,{ CTL_KERN, KERN_BOOTTIME }也会测量Unix Time。因此,只需减去这两个time_points即可获得启动时间。以下是修改已接受答案的OS X解决方案的方法:

std::chrono::system_clock

注意:

  • 最佳std::chrono::milliseconds uptime() { using namespace std::chrono; timeval ts; auto ts_len = sizeof(ts); int mib[2] = { CTL_KERN, KERN_BOOTTIME }; auto constexpr mib_len = sizeof(mib)/sizeof(mib[0]); if (sysctl(mib, mib_len, &ts, &ts_len, nullptr, 0) == 0) { system_clock::time_point boot{seconds{ts.tv_sec} + microseconds{ts.tv_usec}}; return duration_cast<milliseconds>(system_clock::now() - boot); } return 0ms; } 为您完成单位转换。如果您的代码中包含chrono(例如,将秒数转换为毫秒数),请将其重写为1000进行转换。
  • 如果编译,您可以依赖隐式计时持续时间单位转换。如果他们没有编译,这意味着您要求截断,并且您可以明确要求使用chrono进行截断。
  • 如果能使代码更具可读性,可以在函数中本地使用 using

答案 2 :(得分:2)

如何自定义日志消息有一个boost example

在其中,作者正在实现一个简单的函数byte[],以便为不同的平台(包括Windows,OSx,Linux以及BSD)获得系统正常运行时间。