1. 程式人生 > >iOS 獲取系統啟動時間

iOS 獲取系統啟動時間

做一個流量監控,之前的程式碼是通過sysctl讀取程序列表,取得kernel_task程序的啟動時間作為系統啟動時間,如果系統重啟就需要把網絡卡記錄的流量全部累加,否則用本次讀取的網絡卡流量資料減去上一次記錄的資料認為是這段時間內使用者產生的流量。

在iOS9上 sysctl被封了,於是這段程式碼就掛了。沒辦法拿到系統啟動時間,就會不停的累加網絡卡記錄的全部流量。

使用sysctl取得kernel_task啟動時間

+ (NSDate *)systemStartTime
{
    size_t length = 0;
    static const int name[] = {CTL_KERN, KERN_PROC, KERN_PROC_ALL, 0
}; int err = sysctl( (int *) name, (sizeof(name) / sizeof(*name)) - 1, NULL, &length, NULL, 0); if (err == -1) { err = errno; } if (err == 0) { struct kinfo_proc *procBuffer = (struct kinfo_proc *)malloc(length); if(procBuffer == NULL) { return
nil; } sysctl( (int *) name, (sizeof(name) / sizeof(*name)) - 1, procBuffer, &length, NULL, 0); int count = (int)length / sizeof(struct kinfo_proc); for (int i = 0; i < count; ++i) { NSString *procName = [NSString stringWithCString:procBuffer[i].kp_proc.p_comm encoding:NSUTF8StringEncoding]; if
([procName isEqualToString:@"kernel_task"]) { return [NSDate dateWithTimeIntervalSince1970:procBuffer[i].kp_proc.p_un.__p_starttime.tv_sec]; } } } return nil; }

使用sysctlbyname取得boottime

+ (NSDate *)systemStartTime {
    size_t size;
    sysctlbyname("kern.boottime", NULL, &size, NULL, 0);
    char *boot_time = malloc(size);
    sysctlbyname("kern.boottime", boot_time, &size, NULL, 0);
    uint32_t timestamp = 0;
    memcpy(&timestamp, boot_time, sizeof(uint32_t));
    free(boot_time);
    NSDate* bootTime = [NSDate dateWithTimeIntervalSince1970:timestamp];
    NSLog(@"BootTime: %@", bootTime);
    return  bootTime;
}

boottime 也是有問題的,就是使用者手動設定系統時間後,bootime會變動成手動設定的那個時刻;另外mach_absolute_time讀取出來的tick數和bootime是一致的,個人猜測boottime其實就是換算mach_absolute_time()的結果。