在Objective-C中获取类似top
命令的系统进程信息,可以通过系统级API实现,以下为详细实现方案,适用于macOS开发(iOS因沙盒限制无法获取其他进程信息):
核心实现步骤
获取进程ID列表
- (NSArray *)getAllProcessIDs { int mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_ALL, 0}; size_t length = 0; // 获取数据长度 sysctl(mib, 4, NULL, &length, NULL, 0); // 分配内存 struct kinfo_proc *processList = malloc(length); sysctl(mib, 4, processList, &length, NULL, 0); int processCount = (int)(length / sizeof(struct kinfo_proc)); NSMutableArray *pids = [NSMutableArray array]; for (int i = 0; i < processCount; i++) { [pids addObject:@(processList[i].kp_proc.p_pid)]; } free(processList); return [pids copy]; }
获取单个进程详细信息
#import <libproc.h> #import <mach/mach.h> - (NSDictionary *)processInfoForPID:(pid_t)pid { // 1. 获取进程名称 char name[256]; proc_name(pid, name, sizeof(name)); NSString *processName = [NSString stringWithUTF8String:name]; // 2. 获取CPU使用率(需两次采样计算) static NSMutableDictionary *prevTimeDict; if (!prevTimeDict) prevTimeDict = [NSMutableDictionary dictionary]; struct proc_taskinfo taskInfo; proc_pidinfo(pid, PROC_PIDTASKINFO, 0, &taskInfo, sizeof(taskInfo)); double cpuUsage = 0.0; if (prevTimeDict[@(pid)]) { uint64_t prevTime = [prevTimeDict[@(pid)] unsignedLongLongValue]; uint64_t timeDiff = taskInfo.pti_total_user + taskInfo.pti_total_system - prevTime; cpuUsage = (timeDiff / 10000000.0); // 转换为百分比 } prevTimeDict[@(pid)] = @(taskInfo.pti_total_user + taskInfo.pti_total_system); // 3. 获取内存占用 struct proc_regioninfo regionInfo; proc_pidinfo(pid, PROC_PIDREGIONINFO, 0, ®ionInfo, sizeof(regionInfo)); unsigned long memoryUsage = regionInfo.pri_private_resident_size / 1024; // KB return @{ @"pid": @(pid), @"name": processName, @"cpu": @(cpuUsage), @"memory": @(memoryUsage) }; }
整合所有进程数据
- (NSArray *)getTopProcesses { NSArray *pids = [self getAllProcessIDs]; NSMutableArray *processes = [NSMutableArray array]; for (NSNumber *pidNum in pids) { pid_t pid = [pidNum intValue]; NSDictionary *info = [self processInfoForPID:pid]; if (info) [processes addObject:info]; } // 按CPU使用率排序 NSSortDescriptor *sortDescriptor = [NSSortDescriptor sortDescriptorWithKey:@"cpu" ascending:NO]; return [processes sortedArrayUsingDescriptors:@[sortDescriptor]]; }
关键说明
-
权限要求:
- 需要开启
com.apple.security.get-task-all
权限(在Entitlements
文件中) - macOS应用需签名并开启沙盒的
Allow Debugging
权限
- 需要开启
-
性能优化:
- 避免频繁调用(建议采样间隔≥1秒)
- 使用缓存存储上次采样时间
- 过滤
pid=0
的系统进程
-
iOS限制:
- iOS只能获取当前应用的信息
- 使用
NSProcessInfo
获取当前进程数据:double cpu = [NSProcessInfo processInfo].processorLoad; long memory = [NSProcessInfo processInfo].physicalMemory / 1024;
输出示例
[ {"pid": 123, "name": "Xcode", "cpu": 45.2, "memory": 102400}, {"pid": 456, "name": "Safari", "cpu": 22.1, "memory": 87600}, ... ]
替代方案(系统命令)
若无需实时控制,可直接调用top
命令:
NSTask *task = [[NSTask alloc] init]; [task setLaunchPath:@"/usr/bin/top"]; [task setArguments:@[@"-l", @"1", @"-n", @"10"]]; // 采样1次,前10进程 NSPipe *pipe = [NSPipe pipe]; [task setStandardOutput:pipe]; [task launch]; NSData *data = [[pipe fileHandleForReading] readDataToEndOfFile]; NSString *output = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
注意事项
- 内存管理:使用
free()
释放malloc
分配的内存 - 错误处理:检查
sysctl
/proc_pidinfo
返回值 - 实时性:CPU使用率需两次采样计算差值
- 沙盒限制:完整功能需关闭App Sandbox
引用说明:本文实现基于Apple官方文档 proc_info(2) 及 sysctl(3) 系统调用。
原创文章,发布者:酷番叔,转转请注明出处:https://cloud.kd.cn/ask/5061.html