正如其中一位 cmets 所述,POSIX'sclock_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)
对于那些仍然对在 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)