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()的结果。

猜你喜欢

转载自blog.csdn.net/wadahana/article/details/50315089