Rus*_*inn 49
我想我已经解决了.
time()
当设备处于睡眠状态时继续递增,但当然可以由操作系统或用户操纵.但是,内核启动时间(系统上次启动时的时间戳)也会在系统时钟更改时发生更改,因此即使这两个值都不固定,它们之间的偏移也是如此.
#include <sys/sysctl.h>
- (time_t)uptime
{
struct timeval boottime;
int mib[2] = {CTL_KERN, KERN_BOOTTIME};
size_t size = sizeof(boottime);
time_t now;
time_t uptime = -1;
(void)time(&now);
if (sysctl(mib, 2, &boottime, &size, NULL, 0) != -1 && boottime.tv_sec != 0) {
uptime = now - boottime.tv_sec;
}
return uptime;
}
Run Code Online (Sandbox Code Playgroud)
nyg*_*nyg 17
正如其中一条评论所述,POSIX clock_gettime()
是在iOS 10和macOS 10.12中实现的.当与CLOCK_MONOTONIC
参数一起使用时,它似乎确实返回正常运行时间值.但是,文档不保证这一点:
对于此时钟,clock_gettime()返回的值表示自过去未指定的点(例如,系统启动时间或Epoch)以来的时间量(以秒和纳秒为单位).系统启动时间后,这一点不会改变.
以及相应macOS手册页的摘录:
CLOCK_MONOTONIC时钟单调递增,跟踪任意点以来的时间,并在系统处于睡眠状态时继续递增.
CLOCK_MONOTONIC_RAW时钟单调递增,跟踪自CLOCK_MONOTONIC等任意点以来的时间.但是,此时钟不受频率或时间调整的影响.不应将其与其他系统时间源进行比较.
CLOCK_MONOTONIC_RAW_APPROX与CLOCK_MONOTONIC_RAW类似,但在上下文切换时读取系统缓存的值.这可以更快地读取,但是会丢失准确性,因为它可能返回毫秒级的值.
CLOCK_UPTIME_RAW时钟以与CLOCK_MONOTONIC_RAW相同的方式单调递增,但在系统处于睡眠状态时不会递增.在应用适当的mach_timebase转换后,返回的值与mach_absolute_time()的结果相同.
请注意,CLOCK_MONOTONIC
返回精度为微秒CLOCK_MONOTONIC_RAW
级,精度为纳秒级.
SWIFT代码:
func uptime() -> timespec {
var uptime = timespec()
if 0 != clock_gettime(CLOCK_MONOTONIC_RAW, &uptime) {
fatalError("Could not execute clock_gettime, errno: \(errno)")
}
return uptime
}
print(uptime()) // timespec(tv_sec: 636705, tv_nsec: 750700397)
Run Code Online (Sandbox Code Playgroud)
对于那些仍然对在Swift中获取内核启动时间感兴趣的人:
func kernelBootTime() -> timeval {
var mib = [ CTL_KERN, KERN_BOOTTIME ]
var bootTime = timeval()
var bootTimeSize = MemoryLayout<timeval>.size
if 0 != sysctl(&mib, UInt32(mib.count), &bootTime, &bootTimeSize, nil, 0) {
fatalError("Could not get boot time, errno: \(errno)")
}
return bootTime
}
print(kernelBootTime()) // timeval(tv_sec: 1499259206, tv_usec: 122778)
Run Code Online (Sandbox Code Playgroud)
Vit*_*ali 14
列出的所有示例中都存在竞争条件:如果时间有变化(NTP或用户修改),代码将竞争,时钟不再单调.
正确的实施是:
#include <sys/sysctl.h>
static int64_t us_since_boot() {
struct timeval boottime;
int mib[2] = {CTL_KERN, KERN_BOOTTIME};
size_t size = sizeof(boottime);
int rc = sysctl(mib, 2, &boottime, &size, NULL, 0);
if (rc != 0) {
return 0;
}
return (int64_t)boottime.tv_sec * 1000000 + (int64_t)boottime.tv_usec;
}
- (int64_t)us_uptime
{
int64_t before_now;
int64_t after_now;
struct timeval now;
after_now = us_since_boot();
do {
before_now = after_now;
gettimeofday(&now, NULL);
after_now = us_since_boot();
} while (after_now != before_now);
return (int64_t)now.tv_sec * 1000000 + (int64_t)now.tv_usec - before_now;
}
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
16289 次 |
最近记录: |