MacOS上基于GCD的DISPATCH_SOURCE_TYPE_MEMORYPRESSURE检测失效问题
问题
我使用Grand Central Dispatch框架,通过DISPATCH_SOURCE_TYPE_MEMORYPRESSURE处理内存压力变化,以下是我的Objective-C程序:
#import <Foundation/Foundation.h> #import <dispatch/dispatch.h> int main(int argc, const char * argv[]) { @autoreleasepool { NSLog(@"Starting memory pressure monitoring..."); // 创建内存压力事件的调度源 dispatch_source_t memoryPressureSource = dispatch_source_create( DISPATCH_SOURCE_TYPE_MEMORYPRESSURE, 0, DISPATCH_MEMORYPRESSURE_WARN | DISPATCH_MEMORYPRESSURE_CRITICAL | DISPATCH_MEMORYPRESSURE_NORMAL, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0) ); if (memoryPressureSource == NULL) { NSLog(@"Failed to create dispatch source"); return 1; } // 设置内存压力事件的处理块 dispatch_source_set_event_handler(memoryPressureSource, ^{ NSLog(@"Memory pressure event handled"); }); dispatch_source_set_registration_handler(memoryPressureSource, ^{ NSLog(@"Memory pressure event registered"); }); dispatch_activate(memoryPressureSource); // 保持主线程活跃以处理调度源事件 dispatch_main(); } return 0; }
我通过命令clang -framework Foundation -framework CoreFoundation -o memory_pressure_tracker ./untitled.mm编译并运行该程序,同时在另一个终端执行sudo memory_pressure -l critical模拟临界内存压力。尽管活动监视器显示内存压力变化,但程序仅输出以下启动和注册日志:
2024-09-10 10:41:27.048 memory_pressure_tracker[130:11424978] Starting memory pressure monitoring... 2024-09-10 10:41:27.048 memory_pressure_tracker[130:11424985] Memory pressure event registered
未记录内存压力事件日志。我在MacOS Sonoma 14.6.1(M1 Max)上进行测试,请问问题出在哪里?
解决方案
- 权限缺失:
memory_pressure工具触发的系统级内存压力通知,需要程序拥有com.apple.security.taskport权限才能接收。默认命令行编译的程序没有该权限,因此无法捕获模拟的压力事件。 - 事件处理未读取压力级别:当前的事件处理块仅输出通用日志,未读取实际压力等级数据,但这不是接收不到事件的核心原因。
- 队列选择不合理:使用高优先级全局队列处理内存压力事件可能在资源紧张时抢占其他任务资源,建议改用主队列或低优先级全局队列。
修复步骤
- 创建权限配置文件:新建
entitlements.plist文件,内容如下:
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <dict> <key>com.apple.security.taskport</key> <true/> </dict> </plist>
- 重新编译并签名:执行以下命令完成编译和权限签名:
clang -framework Foundation -framework CoreFoundation -o memory_pressure_tracker ./untitled.mm codesign -s - --entitlements entitlements.plist memory_pressure_tracker
- 优化事件处理逻辑:修改事件处理块,读取并区分不同压力等级:
dispatch_source_set_event_handler(memoryPressureSource, ^{ unsigned long pressureLevel = dispatch_source_get_data(memoryPressureSource); if (pressureLevel & DISPATCH_MEMORYPRESSURE_CRITICAL) { NSLog(@"Critical memory pressure detected"); } else if (pressureLevel & DISPATCH_MEMORYPRESSURE_WARN) { NSLog(@"Warning memory pressure detected"); } else if (pressureLevel & DISPATCH_MEMORYPRESSURE_NORMAL) { NSLog(@"Memory pressure returned to normal"); } });
- 重新运行测试:启动签名后的程序,再次执行
sudo memory_pressure -l critical模拟压力,程序将正常输出对应事件日志。
内容的提问来源于stack exchange,提问作者Mikhail Leliakin
相关产品推荐
相关产品推荐

