9

システムの起動時間を取得NSDateまたは表すAPIはありますか?NSTimeIntervalおよびCoreMotionなどの一部のAPIは[NSProcessInfo systemUptime]、起動後の時間を返します。これらの稼働時間の値をNSDatesと正確に相関させる必要があります(約1ミリ秒)。

起動からの時間は表面上はより高い精度を提供しますが、すでに100ナノ秒のオーダーの精度を提供していることは簡単にわかりNSDateます。マイクロ秒未満のものは、割り込みレイテンシとPCBクロックジッターを測定しているだけです。

明らかなことは、現在の時刻から稼働時間を差し引くことです[NSDate date]。ただし、これは、2つのシステムコール間で時間が変わらないことを前提としています。これは、達成するのが難しいことです。さらに、呼び出しの間にスレッドがプリエンプトされると、すべてが破棄されます。回避策は、プロセスを数回繰り返し、最小の結果を使用することですが、やっかいです。

NSDateシステムの稼働時間から現在の時刻でオブジェクトを生成するために使用するマスターオフセットが必要ですが、それを取得する方法は本当にありませんか?

4

5 に答える 5

8

OSXでは、 sysctl()を使用できます。これは、OSXUnixユーティリティuptimeがそれを行う方法です。 ソースコードが利用可能です-を検索してboottimeください。

ただし、公正な警告ですが、iOSではこれが機能するかどうかわかりません。

更新:いくつかのコードが見つかりました:)

#include <sys/types.h>
#include <sys/sysctl.h>  

#define MIB_SIZE 2  

int mib[MIB_SIZE];
size_t size;
struct timeval  boottime;

mib[0] = CTL_KERN;
mib[1] = KERN_BOOTTIME;
size = sizeof(boottime);
if (sysctl(mib, MIB_SIZE, &boottime, &size, NULL, 0) != -1)
{
    // successful call
    NSDate* bootDate = [NSDate dateWithTimeIntervalSince1970:
                               boottime.tv_sec + boottime.tv_usec / 1.e6];
}

これが機能するかどうかを確認してください...

于 2012-07-01T14:56:23.183 に答える
2

を使用して受け入れられた答えは機能しますが、少なくとも私のテスト(Darwinカーネルバージョン11.4.2)では、forsystclによって返される値は常に秒単位です(マイクロ秒フィールド、、は0です)。これは、結果として生じる時間が最大1秒ずれることを意味しますが、これはあまり正確ではありません。 sysctlKERN_BOOTTIMEtv_usec

また、その値をとの違いから実験的に導き出された値と比較するREALTIME_CLOCKと、数秒異なる場合があるため、値が稼働時間クロックの時間基準に正確に対応しているCALENDAR_CLOCKかどうかは不明です。KERN_BOOTTIME

于 2012-11-29T19:58:39.867 に答える
1

別の方法があります。受け入れられた回答とはわずかに異なる(少ないまたは多い)結果が得られる可能性があります

私はそれらを比較しました。OSX 10.9.3では-7秒、iOS7.1.1では+2秒の違いがあります

私が理解しているように、この方法は壁掛け時計が変更された場合に同じ結果をもたらしますが、受け入れられた答えは壁掛け時計が変更された場合に異なる結果をもたらします...

ここにコード:

static CFAbsoluteTime getKernelTaskStartTime(void) {
    enum { MICROSECONDS_IN_SEC = 1000 * 1000 };
    struct kinfo_proc   info;
    bzero(&info, sizeof(info));

    // Initialize mib, which tells sysctl the info we want, in this case
    // we're looking for information about a specific process ID = 0.
    int mib[] = {CTL_KERN, KERN_PROC, KERN_PROC_PID, 0};

    // Call sysctl.
    size_t size = sizeof(info);
    const int sysctlResult = sysctl(mib, COUNT_ARRAY_ELEMS(mib), &info, &size, NULL, 0);
    assert(0 != sysctlResult);

    const struct timeval * timeVal = &(info.kp_proc.p_starttime);
    NSTimeInterval result = -kCFAbsoluteTimeIntervalSince1970;
    result += timeVal->tv_sec;
    result += timeVal->tv_usec / (double)MICROSECONDS_IN_SEC;
    return result;
}
于 2014-06-27T12:49:37.703 に答える
1

このカテゴリを参照してください

NSDate + BootTime.h

#import <Foundation/Foundation.h>

@interface NSDate (BootTime)

+ (NSDate *)bootTime;

+ (NSTimeInterval)bootTimeTimeIntervalSinceReferenceDate;

@end

NSDate + BootTime.m

#import "NSDate+BootTime.h"

#include <sys/types.h>
#include <sys/sysctl.h>

@implementation NSDate (BootTime)

+ (NSDate *)bootTime {
    return [NSDate dateWithTimeIntervalSinceReferenceDate:[NSDate bootTimeTimeIntervalSinceReferenceDate]];
}

+ (NSTimeInterval)bootTimeTimeIntervalSinceReferenceDate {
    return getKernelTaskStartTime();
}

////////////////////////////////////////////////////////////////////////
#pragma mark - Private
////////////////////////////////////////////////////////////////////////

#define COUNT_ARRAY_ELEMS(arr) sizeof(arr)/sizeof(arr[0])

static CFAbsoluteTime getKernelTaskStartTime(void) {
    enum { MICROSECONDS_IN_SEC = 1000 * 1000 };
    struct kinfo_proc   info;
    bzero(&info, sizeof(info));

    // Initialize mib, which tells sysctl the info we want, in this case
    // we're looking for information about a specific process ID = 0.
    int mib[] = {CTL_KERN, KERN_PROC, KERN_PROC_PID, 0};

    // Call sysctl.
    size_t size = sizeof(info);
    const int sysctlResult = sysctl(mib, COUNT_ARRAY_ELEMS(mib), &info, &size, NULL, 0);
    if (sysctlResult != -1) {

        const struct timeval * timeVal = &(info.kp_proc.p_starttime);
        NSTimeInterval result = -kCFAbsoluteTimeIntervalSince1970;
        result += timeVal->tv_sec;
        result += timeVal->tv_usec / (double)MICROSECONDS_IN_SEC;
        return result;

    }

    return 0;
}

@end
于 2015-08-03T13:51:32.803 に答える
0

NSDateとは異なり、mach/mach_time.h内のルーチンは単調に増加することが保証されています。

于 2012-07-01T15:15:20.767 に答える