Получить точное время загрузки системы на iOS / OS X

Существует ли API для получения NSDate или NSTimeInterval представляющих время загрузки системы? Некоторые API, такие как [NSProcessInfo systemUptime] и Core Motion возвращают время с момента загрузки. Мне нужно точно сопоставить эти значения времени безотказной работы с NSDate s примерно до миллисекунды.

Время, которое загружается якобы, обеспечивает более NSDate точность, но легко видеть, что NSDate уже обеспечивает точность порядка 100 наносекунд, а все, что находится под микросекундой, просто измеряет задержку прерывания и джиттер часов PCB.

Очевидная вещь – вычесть время безотказной работы с текущего времени [NSDate date] . Но это предполагает, что время между двумя системными вызовами не меняется, что, к сожалению, трудно выполнить. Более того, если поток выгружен между вызовами, все отбрасывается. Обходной путь состоит в том, чтобы повторить процесс несколько раз и использовать наименьший результат, но yuck.

NSDate должен иметь NSDate смещение, которое он использует для генерации объектов с текущим временем от времени безотказной работы системы, действительно ли нет способа его получить?

В OSX вы можете использовать sysctl () . Именно так работает время автономной uptime OSX Unix. Исходный код доступен – поиск boottime .

Справедливое предупреждение, хотя в iOS я понятия не имею, будет ли это работать.

UPDATE: нашел код 🙂

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

посмотрите, работает ли это …

Принятый ответ, используя systcl , работает, но значения, возвращаемые sysctl для KERN_BOOTTIME , по крайней мере в моем тестировании (Darwin Kernel Version 11.4.2), всегда целые секунды (поле микросекунд, tv_usec , равно 0). Это означает, что результирующее время может составлять до 1 секунды, что не очень точно.

Кроме того, сравнив это значение с одним, полученным экспериментально из разницы между REALTIME_CLOCK и CALENDAR_CLOCK , они иногда различаются на пару секунд, поэтому неясно, соответствует ли значение KERN_BOOTTIME точному времени для часов времени безотказной работы.

Есть и другой способ. Это может привести к тому, что результат несколько отличается (меньше или больше), чем принятый ответ

Я их сравнил. Я получаю разницу -7 секунд для OSX 10.9.3 и +2 секунды для iOS 7.1.1

Поскольку я понимаю, что этот способ дает тот же результат, если настенные часы изменились, но принятый ответ дает разные результаты, если настенные часы изменились …

Здесь код:

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

В отличие от NSDate, подпрограммы внутри mach / time_h гарантируют монотонное увеличение.

Вернуться к этой категории

.час

 #import <Foundation/Foundation.h> @interface NSDate (BootTime) + (NSDate *)bootTime; + (NSTimeInterval)bootTimeTimeIntervalSinceReferenceDate; @end 

.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 
  • Можно ли зарегистрироваться для уведомлений Push Push для CKS без необходимости спрашивать пользователя?
  • postbuild Сценарий UIAutomation не работает в jenkins
  • Подклассы против протоколов
  • Функция, которая принимает последовательность типа
  • Переопределить инициализатор по умолчанию суперкласса в разных быстрых файлах
  • Как извлечь список строк электронной почты или почтового ящика в тексте или проверить, соответствует ли строка правильному адресу электронной почты?
  • Что означает код ошибки NSURLConnection «-1009»?
  • Возможность подключения VPN с клиента к tunnel_server (с использованием приложения SimpleTunnel от Apple), но неспособной просматривать Интернет на устройстве
  • Какая польза от использования dispatch_sync, если он должен дождаться завершения основного потока?
  • Могут ли разработчики использовать iCloud в приложениях Windows?
  • Связь Bluetooth между OSX и iOS
  • Давайте будем гением компьютера.