OOM 的全称是 Out-Of-Memory,是由于 iOS 的 Jetsam 机制造成的一种“另类” Crash,它不同于常规的 Crash,通过 Signal 捕获等 Crash 监控方案无法捕获到 OOM 事件。
目前猜测两种情况会造成 OOM,
XNU 中 .20.55/bsd/sys/kern_memorystatus.h.auto.html 、.70.16/bsd/kern/auto.html 提供了一些函数和宏,我们可以在 root 权限下使用这些宏和函数来获取当前状态下的所有 App 的 oom 内存阈值,并且基于 PID 甚至可以修改进程的 内存阈值,达到增大 oom内存阈值的效果。
对我们最有用的信息如下:
// 获取进程的 pid、优先级、状态、内存阈值等信息
typedef struct memorystatus_priority_entry {pid_t pid;int32_t priority;uint64_t user_data;int32_t limit;uint32_t state;
} memorystatus_priority_entry_t;// 基于下面这些宏可以达到查询内存阈值等信息,也可以修改内存阈值等
/* Commands */
#define MEMORYSTATUS_CMD_GET_PRIORITY_LIST 1
#define MEMORYSTATUS_CMD_SET_PRIORITY_PROPERTIES 2
#define MEMORYSTATUS_CMD_GET_JETSAM_SNAPSHOT 3
#define MEMORYSTATUS_CMD_GET_PRESSURE_STATUS 4
#define MEMORYSTATUS_CMD_SET_JETSAM_HIGH_WATER_MARK 5 /* Set active memory limit = inactive memory limit, both non-fatal */
#define MEMORYSTATUS_CMD_SET_JETSAM_TASK_LIMIT 6 /* Set active memory limit = inactive memory limit, both fatal */
#define MEMORYSTATUS_CMD_SET_MEMLIMIT_PROPERTIES 7 /* Set memory limits plus attributes independently */
#define MEMORYSTATUS_CMD_GET_MEMLIMIT_PROPERTIES 8 /* Get memory limits plus attributes */
#define MEMORYSTATUS_CMD_PRIVILEGED_LISTENER_ENABLE 9 /* Set the task's status as a privileged memory notifications */
#define MEMORYSTATUS_CMD_PRIVILEGED_LISTENER_DISABLE 10 /* Reset the task's status as a privileged memory notifications */
/* Commands that act on a group of processes */
#define MEMORYSTATUS_CMD_GRP_SET_PROPERTIES 100
我们可以创建一个如下代码的程序
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include "kern_memorystatus.h"#define NUM_ENTRIES 1024
char *state_to_text(int State)
{// Convert kMemoryStatus constants to a textual representationstatic char returned[80];sprintf (returned, "0x%02x ",State);if (State & kMemorystatusSuspended) strcat(returned,"Suspended,");if (State & kMemorystatusFrozen) strcat(returned,"Frozen,");if (State & kMemorystatusWasThawed) strcat(returned,"WasThawed,");if (State & kMemorystatusTracked) strcat(returned,"Tracked,");if (State & kMemorystatusSupportsIdleExit) strcat(returned,"IdleExit,");if (State & kMemorystatusDirty) strcat(returned,"Dirty,");if (returned[strlen(returned) -1] == ',')returned[strlen(returned) -1] = '