iPhone上的mach_absolute_time基于什么?

37

我使用这段代码来跟踪最近一次重启的时间:

+ (float) secondsSinceLastReboot{
     return ((float)(mach_absolute_time())) * ((float)timebase.numer) / ((float)timebase.denom) / 1000000000.0f;
}

我曾认为mach_absolute_time()是基于设备上一次启动时间的,就像Mac上一样。但它似乎不是以此为基础。实际上,我不知道它基于什么。

看看以下行为(今天的日期是2009-09-20):

lastRebootTime = [[NSDate date] addTimeInterval:-[self secondsSinceLastReboot]];
//last Reboot Time will contain : 2009-09-20 07:42:14 +0100

我绝对确定那个时候没有重新启动我的设备。我的设备已经一个星期没有启动了。

此外,当我拔掉设备的线缆并运行这个应用程序时,似乎当设备进入睡眠状态时,lastRebootTime会开始向未来移动。似乎 mach_absolute_time 没有考虑到睡眠时间。或者我理解错了?

我真的很想能够获取设备上次重启的时间戳。有什么想法吗?


你可以从CoreAudio实用类中包含“CAHostTimeBase.h”,请参阅https://developer.apple.com/library/ios/qa/qa1643/_index.html。 - Ol Sen
3个回答

56

我自己也遇到了一些问题。由于缺乏文档,所以只能通过实验来解决。以下是我的研究结果:

mach_absolute_time依赖于设备的处理器。它返回自设备上次启动(也称为正常运行时间)以来的时钟滴答数。为了让它以人类可读形式显示,您需要使用 mach_timebase_info(一个比率)的结果进行修改,该函数会返回十亿分之一秒(纳秒)。为了使其更易于使用,我使用以下函数:

#include <mach/mach_time.h>

int getUptimeInMilliseconds()
{
    const int64_t kOneMillion = 1000 * 1000;
    static mach_timebase_info_data_t s_timebase_info;

    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        (void) mach_timebase_info(&s_timebase_info);
    });

    // mach_absolute_time() returns billionth of seconds,
    // so divide by one million to get milliseconds
    return (int)((mach_absolute_time() * s_timebase_info.numer) / (kOneMillion * s_timebase_info.denom));
}

9
看起来你的实验结果与苹果工程师得出的解决方案相同。 https://developer.apple.com/library/mac/qa/qa1398/_index.html - user371320
就此而言,后者似乎是针对OSX的。 - JohnK
4
这个函数在 iOS 上运行不正确。在返回的字符串中,您进行了整数值计算。由于 iPhone 5 的 s_timebase_info.numer = 125 和 s_timebase_info.denom = 3,所以在请求之间大约40秒内,您最终可以获得相同的正常运行时间。为了正确性,请将 mach_absolute_time() 乘以浮点数1.0。 - malex
在我的测试中,当iOS处于睡眠状态时,此函数将不会计数。请参阅此问题的已接受答案:https://dev59.com/0Wcs5IYBdhLWcg3w64Ca - Tim

9
如果你不太在意计算时间,可以使用来自Foundation的简单Obj-C类。
NSTimeInterval systemUptime = [[NSProcessInfo processInfo] systemUptime];

“Completion time” 是什么意思? - Eddy
1
抱歉打错了,“计算时间”。我的意思是,Obj-C 的运行速度比纯 C 代码慢一些。 - malex
我在模拟器中使用此代码进行检查,但无法获得差异,在重新启动模拟器后,两个systemUptime相同。 - g212gs
2
@g212gs 注意,这是系统正常运行时间!模拟器的系统是OSX。因此,您会得到正确的答案-在重新启动Mac之前,它将保持相同的正常运行时间。 - malex

3
在需要使用Swift的情况下(在4.2和5.0版本中均可使用)。
let beginTime = mach_absolute_time()

// do something...

var baseInfo = mach_timebase_info_data_t(numer: 0, denom: 0)
if mach_timebase_info(&baseInfo) == KERN_SUCCESS {
    let finiTime = mach_absolute_time()
    
    let nano = (finiTime - beginTime) * UInt64(baseInfo.numer) / UInt64(baseInfo.denom)
}

现在您可以使用 clock_gettime_nsec_np(CLOCK_UPTIME_RAW) 一次调用获取纳秒级时间。此外,如果您想要包括睡眠时间,可以使用 clock_gettime_nsec_np(CLOCK_MONOTONIC_RAW) - robinst

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接