ITPub博客

首页 > IT职业 > IT职场 > iOS Out-Of-Memory 原理阐述及方案调研

iOS Out-Of-Memory 原理阐述及方案调研

IT职场 作者:tuba 时间:2021-09-09 10:17:33 0 删除 编辑


图片描述

什么是 OOM?

OOM 的全称是 Out-Of-Memory,是由于 iOS 的 Jetsam 机制造成的一种“另类” Crash,它不同于常规的 Crash,通过 Signal 捕获等 Crash 监控方案无法捕获到 OOM 事件。

为什么会发生 oom?

目前猜测两种情况会造成 OOM,

  1. 系统整体内存使用较高,系统基于优先级杀死优先级较低的 App

  2. 当前使用的 App 达到了 “high water mark”,也就是达到了系统对单个 App 的内存限制,系统会将你 Kill

验证方案 1 :

XNU 中 opensource.apple.com/source/xnu/… 、opensource.apple.com/source/xnu/… 提供了一些函数和宏,我们可以在 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 listener w.r.t memory notifications  */
#define MEMORYSTATUS_CMD_PRIVILEGED_LISTENER_DISABLE  10   /* Reset the task's status as a privileged listener w.r.t 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 representation

    static 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] = '

来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/1536/viewspace-2819609/ ,如需转载,请注明出处,否则将追究法律责任。

请登录后发表评论 登录
全部评论

注册时间:2019-04-15

  • 博文量
    0
  • 访问量
    784