16

How do I get system up time since the start of the system? All I found was time since epoch and nothing else.

For example, something like time() in ctime library, but it only gives me a value of seconds since epoch. I want something like time() but since the start of the system.

Deanie
  • 2,316
  • 2
  • 19
  • 35
user3426112
  • 401
  • 1
  • 3
  • 11

3 Answers3

37

It is OS dependant and already answered for several systems on stackoverflow.

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

Windows ...

using GetTickCount64() (resolution usually 10-16 millisecond)

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

Linux ...

... using /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*1000.0)
  );
}

... using sysinfo (resolution 1 second)

#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 ...

... using 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-like systems (or systems supporting CLOCK_UPTIME or CLOCK_UPTIME_PRECISE respectively) ...

... using clock_gettime (resolution see 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
   );
}
Pixelchemist
  • 24,090
  • 7
  • 47
  • 71
  • 2
    Also, is there a cross-platform way of getting it? – user3426112 May 07 '15 at 08:29
  • it must be `static_cast(uptime_seconds*1000)` because `uptime_seconds` include milliseconds, for example `8084.13 * 1000 = 8084130 mS` instead `8084 * 1000 = 8084000 mS` – Mr.Angel Jun 22 '18 at 13:34
3

+1 to the accepted answer. Nice survey. But the OS X answer is incorrect and I wanted to show the correction here.

The sysctl function with an input of { CTL_KERN, KERN_BOOTTIME } on OS X returns the Unix Time the system was booted, not the time since boot. And on this system (and every other system too), std::chrono::system_clock also measures Unix Time. So one simply has to subtract these two time_points to get the time-since-boot. Here is how you modify the accepted answer's OS X solution to do this:

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;
}

Notes:

  • It is best to have chrono do your units conversions for you. If your code has 1000 in it (e.g. to convert seconds to milliseconds), rewrite it to have chrono do the conversion.
  • You can rely on implicit chrono duration unit conversions to be correct if they compile. If they don't compile, that means you're asking for truncation, and you can explicitly ask for truncation with duration_cast.
  • It's ok to use a using directive locally in a function if it makes the code more readable.
Howard Hinnant
  • 206,506
  • 52
  • 449
  • 577
  • ´system_clock´ is not monotonic, in consequence, substracting `now-boot` could result in a wrong, even negative value? – Adrian Maire Oct 16 '19 at 12:35
  • True but it would take someone actively trying to thwart the system to do that. Under normal circumstances the computer's tracking of Unix Time is adjusted by small amounts of time to track the correct time with the accuracy of a cheap quartz clock. Neither daylight saving nor changing time zones impacts the value returned by `system_clock`. And to be pedantic, `now-boot` will likely be a little bit wrong in normal circumstances because macOS doesn't contain a perfect clock. – Howard Hinnant Oct 16 '19 at 13:39
  • @Howard Hinnant: It would take somebody correcting the system time to do it. Or somebody reconfiguring the NTP source. Or a system with a blown clock battery (they last about 10 years) which corrects the system time using NTP during boot. No actively trying to thwart the system required. – Robin Davies Jul 18 '21 at 19:45
2

There is a boost example on how to customize logging messages.

In it the author is implementing a simple function unsigned int get_uptime() to get the system uptime for different platforms including Windows, OSx, Linux as well as BSD.

blurryroots
  • 402
  • 5
  • 12