Android ActivityManagerService--09:进程管理(一)

本文转载自:ActivityManagerService之进程管理(四)

本文基于Android 11.0源码分析

1.初步了解AMS的进程管理

1.1 Linux进程调度优先级和调度策略

  调度优先级和调度策略是操作系统中一个很重要的概念。简而言之,它是系统中CPU资源的管理和控制手段。如何理解?此处进行简单介绍。读者可自行阅读操作系统方面的书籍以加深理解。

  • 相对于在OS上运行的应用进程个数来说,CPU的资源非常有限。

  • 调度优先级是OS分配CPU资源给应用进程时(即调度应用进程运行)需要参考的一个指标。一般而言,优先级高的进程将更有机会得到CPU资源。

  调度策略用于描述OS调度模块分配CPU给应用进程所遵循的规则,即当将CPU控制权交给调度模块时,系统如何选择下一个要运行的进程。此处不能仅考虑各进程的调度优先级,因为存在多个进程具有相同调度优先级的情况。在这种情况下,一个需要考虑的重要因素是,每个进程所分配的时间片及它们的使用情况。

  可简单认为,调度优先级及调度策略二者一起影响了系统分配CPU资源给应用进程。注意,此处的措词为“影响”,而非“控制”。因为对于用户空间可以调用的API来说,如果二者能控制CPU资源分配,那么该系统的安全性会大打折扣。

(1)setpriority

  Linux提供了两个API用于设置调度优先级及调度策略。先来看设置调度优先级的函数setpriority,其原型如下:

int setpriority(int which, int who, int prio);

其中:

  • which和who参数联合使用。

    • 当which为PRIO_PROGRESS时,who代表一个进程;

    • 当which为PRIO_PGROUP时,who代表一个进程组;

    • 当which为PRIO_USER时,who代表一个uid。

  • 第三个参数prio用于设置应用进程的nicer值,可取范围从-20到19。Linux kernel用nicer值来描述进程的调度优先级,该值越大,表明该进程越优(nice),其被调度运行的几率越低。

(2)sched_setscheduler

  下面来看设置调度策略的函数sched_setscheduler,其原型如下:

int sched_setscheduler(pid_t pid, int policy, conststruct sched_param *param);

其中:

  • 第一个参数为进程id。

  • 第二个参数为调度策略。目前Android支持四种调度策略:

    • SCHED_OTHER,标准round-robin分时共享策略(也就是默认的策略);

    • SCHED_BATCH,针对具有batch风格(批处理)进程的调度策略;

    • SCHED_IDLE,针对优先级非常低的适合在后台运行的进程。除此之外,Linux还支持实时(Real-time)调度策略,包括SCHED_FIFO,先入先出调度策略;

    • SCHED_RR,round-robin调度策略,也就是循环调度。这些策略的定义值在Process.java,下面的文章有介绍这个类。

  • param参数中最重要的是该结构体中的sched_priority变量。针对Android中的四种非实时调度策略,该值必须为NULL。

  以上介绍了调度优先级和调度策略的概念。建议读者做个小实验来测试调动优先级及调动策略的作用,步骤如下:

  • 挂载SD卡到PC机并往向其中复制一些媒体文件,然后重新挂载SD卡到手机。该操作就能触发MediaScanner扫描新增的这些媒体文件。

  • 利用top命令查看CPU使用率,会发现进程com.process.media(即MediaScanner所在的进程)占用CPU较高(可达70%以上),原因是该进程会扫描媒体文件,该工作将利用较多的CPU资源。

  • 此时,如果启动另一个进程,然后做一些操作,会发现MediaScanner所在进程的CPU利用率会降下来(例如下降到30%~40%),这表明系统将CPU资源更多地分给了用户正在操作的这个进程。

  出现这种现象的原因是,MediaScannerSerivce的扫描线程将调度优先级设置为11,而默认的调度优先级为0。 相比而言,MediaScannerService优先级真的很高。

1.2 关于Linux进程oom_adj的介绍

  从Linux kernel 2.6.11开始,内核提供了进程的OOM控制机制,目的是当系统出现内存不足(out of memory,简称OOM)的情况时,Kernel可根据进程的oom_adj来选择并杀死一些进程,以回收内存。简而言之,oom_adj可标示Linux进程内存资源的优先级,其可取范围从-16到15,另外有一个特殊值-17用于禁止系统在OOM情况下杀死该进程。和nicer值一样,oom_adj的值越高,那么在OOM情况下,该进程越有可能被杀掉。每个进程的oom_adj初值为0。

  Linux没有提供单独的API用于设置进程的oom_adj。目前的做法就是向/proc/进程id/oom_adj文件中写入对应的oom_adj值,通过这种方式就能调节进程的oom_adj了。

  另外,有必要简单介绍一下Android为Linux Kernel新增的lowmemorykiller(以后简称LMK)模块的工作方式:LMK的职责是根据当前内存大小去杀死对应oom_adj及以上的进程以回收内存。这里有两个关键参数:为LMK设置不同的内存阈值及oom_adj,它们分别由/sys/module/lowmemorykiller/parameters/minfree和/sys/module/lowmemorykiller/parameters/adj控制。

(1)注意:这两个参数的典型设置为:

  • minfree:2048,3072,4096,6144,7168,8192 用于描述不同级别的内存阈值,单位为KB。

  • adj:0,1,2,4,7,15 用于描述对应内存阈值的oom_adj值。

  表示当剩余内存为2048KB时,LMK将杀死oom_adj大于等于0的进程。网络上有一些关于Android手机内存优化的方法,其中一种就利用了LMK的工作原理。

(2)提示
  lowmemorykiller的代码在kernel/drivers/staging/android/lowmemorykiller.c中,感兴趣的读者可尝试自行阅读。

1.3 关于Android中的进程管理的介绍

  前面介绍了Linux OS中进程管理(包括调度和OOM控制)方面的API,但AMS是如何利用它们的呢?这就涉及AMS中的进程管理规则了。这里简单介绍相关规则。

  Android将应用进程分为五大类,分别为Forground类、Visible类、Service类、Background类及Empty类。这五大类的划分各有规则。

(1) Forground类
  该类中的进程重要性最高,属于该类的进程包括下面几种情况:

  • 含一个前端Activity(即onResume函数被调用过了,或者说当前正在显示的那个Activity)。

  • 含一个Service,并且该Service和一个前端Activity绑定(例如Music应用包括一个前端界面和一个播放Service,当我们一边听歌一边操作Music界面时,该Service即和一个前端Activity绑定)。

  • 含一个调用了startForground的Service,或者该进程的Service正在调用其生命周期的函数(onCreate、onStart或onDestroy)。

  • 最后一种情况是,该进程中有BroadcastReceiver实例正在执行onReceive函数。

(2) Visible类
  属于Visible类的进程中没有处于前端的组件,但是用户仍然能看到它们,例如位于一个对话框后的Activity界面。目前该类进程包括两种:

  • 该进程包含一个仅onPause被调用的Activity(即它还在前台,只不过部分界面被遮住)。

  • 或者包含一个Service,并且该Service和一个Visible(或Forground)的Activity绑定(从字面意义上看,这种情况不太好和Forground进程中第二种情况区分)。

(3) Service类、Background类及Empty类
  这三类进程都没有可见的部分,具体情况如下。

  • Service进程:该类进程包含一个Service。此Service通过startService启动,并且不属于前面两类进程。这种进程一般在后台默默地干活,例如前面介绍的MediaScannerService。

  • Background进程:该类进程包含当前不可见的Activity(即它们的onStop被调用过)。系统保存这些进程到一个LRU(最近最少使用)列表。当系统需要回收内存时,该列表中那些最近最少使用的进程将被杀死。

  • Empty进程:这类进程中不包含任何组件。为什么会出现这种不包括任何组件的进程呢?其实很简单,假设该进程仅创建了一个Activity,它完成工作后主动调用finish函数销毁(destroy)自己,之后该进程就会成为Empty进程。系统保留Empty进程的原因是当又重新需要它们时(例如用户在别的进程中通过startActivity启动了它们),可以省去fork进程、创建Android运行环境等一系列漫长而艰苦的工作。

  通过以上介绍可发现,当某个进程和前端显示有关系时,其重要性相对要高,这或许是体现Google重视用户体验的一个很直接的证据吧。

2.AMS的进程管理详情

  AMS的进程管理跟三个类密切关系ProcessList,ProcessRecord和Process。方法的话有updateLruProcessLocked、computeOomAdjLocked、updateOomAdjLocked、applyOomAdjLocked 。其实在AMS中保持所有的进程信息:

//所有的进程信息
final ArrayList<ProcessRecord> mLruProcesses = new ArrayList<ProcessRecord>();
//移除的进程信息
final ArrayList<ProcessRecord> mRemovedProcesses = new ArrayList<ProcessRecord>();
//用pid来查询相关的进程信息
final SparseArray<ProcessRecord> mPidsSelfLocked = new SparseArray<ProcessRecord>();

2.1 ProcessList

// frameworks/base/services/core/java/com/android/server/am/ProcessList.java
public final class ProcessList {
    private static final String TAG = TAG_WITH_CLASS_NAME ? "ProcessList" : TAG_AM;

    // The minimum time we allow between crashes, for us to consider this
    // application to be bad and stop and its services and reject broadcasts.
    static final int MIN_CRASH_INTERVAL = 60*1000;

    // OOM adjustments for processes in various states:

    // Uninitialized value for any major or minor adj fields
    static final int INVALID_ADJ = -10000;

    // Adjustment used in certain places where we don't know it yet.
    // (Generally this is something that is going to be cached, but we
    // don't know the exact value in the cached range to assign yet.)
    static final int UNKNOWN_ADJ = 1001;

    // This is a process only hosting activities that are not visible,
    // so it can be killed without any disruption.
    static final int CACHED_APP_MAX_ADJ = 906;
    static final int CACHED_APP_MIN_ADJ = 900;

    // The B list of SERVICE_ADJ -- these are the old and decrepit
    // services that aren't as shiny and interesting as the ones in the A list.
    static final int SERVICE_B_ADJ = 800;

    // This is the process of the previous application that the user was in.
    // This process is kept above other things, because it is very common to
    // switch back to the previous app.  This is important both for recent
    // task switch (toggling between the two top recent apps) as well as normal
    // UI flow such as clicking on a URI in the e-mail app to view in the browser,
    // and then pressing back to return to e-mail.
    static final int PREVIOUS_APP_ADJ = 700;

    // This is a process holding the home application -- we want to try
    // avoiding killing it, even if it would normally be in the background,
    // because the user interacts with it so much.
    static final int HOME_APP_ADJ = 600;

    // This is a process holding an application service -- killing it will not
    // have much of an impact as far as the user is concerned.
    static final int SERVICE_ADJ = 500;

    // This is a process with a heavy-weight application.  It is in the
    // background, but we want to try to avoid killing it.  Value set in
    // system/rootdir/init.rc on startup.
    static final int HEAVY_WEIGHT_APP_ADJ = 400;

    // This is a process currently hosting a backup operation.  Killing it
    // is not entirely fatal but is generally a bad idea.
    static final int BACKUP_APP_ADJ = 300;

    // This is a process only hosting components that are perceptible to the
    // user, and we really want to avoid killing them, but they are not
    // immediately visible. An example is background music playback.
    static final int PERCEPTIBLE_APP_ADJ = 200;

    // This is a process only hosting activities that are visible to the
    // user, so we'd prefer they don't disappear.
    static final int VISIBLE_APP_ADJ = 100;
    static final int VISIBLE_APP_LAYER_MAX = PERCEPTIBLE_APP_ADJ - VISIBLE_APP_ADJ - 1;

    // This is the process running the current foreground app.  We'd really
    // rather not kill it!
    static final int FOREGROUND_APP_ADJ = 0;

    // This is a process that the system or a persistent process has bound to,
    // and indicated it is important.
    static final int PERSISTENT_SERVICE_ADJ = -700;

    // This is a system persistent process, such as telephony.  Definitely
    // don't want to kill it, but doing so is not completely fatal.
    static final int PERSISTENT_PROC_ADJ = -800;

    // The system process runs at the default adjustment.
    static final int SYSTEM_ADJ = -900;

    // Special code for native processes that are not being managed by the system (so
    // don't have an oom adj assigned by the system).
    static final int NATIVE_ADJ = -1000;

    // Memory pages are 4K.
    static final int PAGE_SIZE = 4*1024;

 private final int[] mOomAdj = new int[] {
            FOREGROUND_APP_ADJ, VISIBLE_APP_ADJ, PERCEPTIBLE_APP_ADJ,
            BACKUP_APP_ADJ, CACHED_APP_MIN_ADJ, CACHED_APP_MAX_ADJ
    };
    // These are the low-end OOM level limits.  This is appropriate for an
    // HVGA or smaller phone with less than 512MB.  Values are in KB.
    private final int[] mOomMinFreeLow = new int[] {
            12288, 18432, 24576,
            36864, 43008, 49152
    };
    // These are the high-end OOM level limits.  This is appropriate for a
    // 1280x800 or larger screen with around 1GB RAM.  Values are in KB.
    private final int[] mOomMinFreeHigh = new int[] {
            73728, 92160, 110592,
            129024, 147456, 184320
    };

  这个类主要是用于OOM的设定值。什么时候会发生OOM呢?跟oom_adj值有很大关系。oom_adj 的值有几个档位如下:

AMS16.png

  为了防止剩余内存过低,Android在内核空间有lowmemorykiller(简称LMK),LMK是通过注册shrinker来触发低内存回收的,这个机制并不太优雅,可能会拖慢Shrinkers内存扫描速度,已从内核4.12中移除,后续会采用用户空间的LMKD + memory cgroups机制,这里先不展开LMK讲解。

  进程刚启动时ADJ等于INVALID_ADJ,当执行完attachApplication(),该进程的curAdj和setAdj不相等,则会触发执行setOomAdj()将该进程的节点/proc/pid/oom_score_adj写入oomadj值。下图参数为Android原生阈值,当系统剩余空闲内存低于某阈值(比如147MB),则从ADJ大于或等于相应阈值(比如900)的进程中,选择ADJ值最大的进程,如果存在多个ADJ相同的进程,则选择内存最大的进程。 如下是64位机器,LMK默认阈值图:

AMS17.png

  在updateOomLevels()过程,会根据手机屏幕尺寸或内存大小来调整scale,默认大多数手机内存都大于700MB,则scale等于1。对于64位手机,阈值会更大些,具体如下。

// frameworks/base/services/core/java/com/android/server/am/ProcessList.javas
    private void updateOomLevels(int displayWidth, int displayHeight, boolean write) {
        // Scale buckets from avail memory: at 300MB we use the lowest values to
        // 700MB or more for the top values.
        float scaleMem = ((float) (mTotalMemMb - 350)) / (700 - 350);

        // Scale buckets from screen size.
        int minSize = 480 * 800;  //  384000
        int maxSize = 1280 * 800; // 1024000  230400 870400  .264
        float scaleDisp = ((float)(displayWidth * displayHeight) - minSize) / (maxSize - minSize);
        if (false) {
            Slog.i("XXXXXX", "scaleMem=" + scaleMem);
            Slog.i("XXXXXX", "scaleDisp=" + scaleDisp + " dw=" + displayWidth
                    + " dh=" + displayHeight);
        }

        float scale = scaleMem > scaleDisp ? scaleMem : scaleDisp;
        if (scale < 0) scale = 0;
        else if (scale > 1) scale = 1;
        int minfree_adj = Resources.getSystem().getInteger(
                com.android.internal.R.integer.config_lowMemoryKillerMinFreeKbytesAdjust);
        int minfree_abs = Resources.getSystem().getInteger(
                com.android.internal.R.integer.config_lowMemoryKillerMinFreeKbytesAbsolute);
        if (false) {
            Slog.i("XXXXXX", "minfree_adj=" + minfree_adj + " minfree_abs=" + minfree_abs);
        }

        final boolean is64bit = Build.SUPPORTED_64_BIT_ABIS.length > 0;

        for (int i = 0; i < mOomAdj.length; i++) {
            int low = mOomMinFreeLow[i];
            int high = mOomMinFreeHigh[i];
            if (is64bit) {
                // Increase the high min-free levels for cached processes for 64-bit
                if (i == 4) high = (high * 3) / 2;
                else if (i == 5) high = (high * 7) / 4;
            }
            mOomMinFree[i] = (int)(low + ((high - low) * scale));
        }

        if (minfree_abs >= 0) {
            for (int i = 0; i < mOomAdj.length; i++) {
                mOomMinFree[i] = (int)((float)minfree_abs * mOomMinFree[i]
                        / mOomMinFree[mOomAdj.length - 1]);
            }
        }

        if (minfree_adj != 0) {
            for (int i = 0; i < mOomAdj.length; i++) {
                mOomMinFree[i] += (int)((float) minfree_adj * mOomMinFree[i]
                        / mOomMinFree[mOomAdj.length - 1]);
                if (mOomMinFree[i] < 0) {
                    mOomMinFree[i] = 0;
                }
            }
        }

        // The maximum size we will restore a process from cached to background, when under
        // memory duress, is 1/3 the size we have reserved for kernel caches and other overhead
        // before killing background processes.
        mCachedRestoreLevel = (getMemLevel(ProcessList.CACHED_APP_MAX_ADJ) / 1024) / 3;

        // Ask the kernel to try to keep enough memory free to allocate 3 full
        // screen 32bpp buffers without entering direct reclaim.
        int reserve = displayWidth * displayHeight * 4 * 3 / 1024;
        int reserve_adj = Resources.getSystem().getInteger(
                com.android.internal.R.integer.config_extraFreeKbytesAdjust);
        int reserve_abs = Resources.getSystem().getInteger(
                com.android.internal.R.integer.config_extraFreeKbytesAbsolute);

        if (reserve_abs >= 0) {
            reserve = reserve_abs;
        }

        if (reserve_adj != 0) {
            reserve += reserve_adj;
            if (reserve < 0) {
                reserve = 0;
            }
        }

        if (write) {
            ByteBuffer buf = ByteBuffer.allocate(4 * (2 * mOomAdj.length + 1));
            buf.putInt(LMK_TARGET);
            for (int i = 0; i < mOomAdj.length; i++) {
                buf.putInt((mOomMinFree[i] * 1024)/PAGE_SIZE);
                buf.putInt(mOomAdj[i]);
            }

            writeLmkd(buf, null);
            SystemProperties.set("sys.sysctl.extra_free_kbytes", Integer.toString(reserve));
            mOomLevelsSet = true;
        }
        // GB: 2048,3072,4096,6144,7168,8192
        // HC: 8192,10240,12288,14336,16384,20480
    }

2.2 ProcessRecord

// frameworks/base/services/core/java/com/android/server/am/ProcessRecord.java
public final class ProcessRecord {
    private static final String TAG = TAG_WITH_CLASS_NAME ? "ProcessRecord" : TAG_AM;

    private final BatteryStatsImpl mBatteryStats; // where to collect runtime statistics//管理进程电量统计
    public final ApplicationInfo info; // all about the first app in the process
    final boolean isolated;     // true if this is a special isolated process //独立进程
    public final int uid;       // uid of process; may be different from 'info' if isolated
    final int userId;           // user of process.
    public final String processName;   // name of the process
    // List of packages running in the process
    public final ArrayMap<String, ProcessStats.ProcessStateHolder> pkgList = new ArrayMap<>();
    UidRecord uidRecord;        // overall state of process's uid.
    //进程运行依赖的包
    ArraySet<String> pkgDeps;   // additional packages we have a dependency on

    //保存IApplicationThread,通过它可以和应用进程交互
    public IApplicationThread thread;  // the actual proc...  may be null only if
                                // 'persistent' is true (in which case we
                                // are in the process of launching the app)
    ProcessState baseProcessTracker;
    BatteryStatsImpl.Uid.Proc curProcBatteryStats;
    public int pid;             // The process of this application; 0 if none
    String procStatFile;        // path to /proc/<pid>/stat
    int[] gids;                 // The gids this process was launched with
    String requiredAbi;         // The ABI this process was launched with
    String instructionSet;      // The instruction set this process was launched with
    boolean starting;           // True if the process is being started
    long lastActivityTime;      // For managing the LRU list//每次updateLruProcessLocked()过程会更新该值
    long lastPssTime;           // Last time we retrieved PSS data
    long nextPssTime;           // Next time we want to request PSS data
    long lastStateTime;         // Last time setProcState changed
    long initialIdlePss;        // Initial memory pss of process for idle maintenance.
    long lastPss;               // Last computed memory pss.
    long lastSwapPss;           // Last computed SwapPss.
    long lastCachedPss;         // Last computed pss when in cached state.
    long lastCachedSwapPss;     // Last computed SwapPss when in cached state.

    //和oom_adj有关
    int maxAdj;                 // Maximum OOM adjustment for this process 进程的adj上限(adjustment)
    int curRawAdj;              // Current OOM unlimited adjustment for this process  当前正在计算的adj,这个值有可能大于maxAdj
    int setRawAdj;              // Last set OOM unlimited adjustment for this process 上次计算的curRawAdj设置到lowmemorykiller系统后的adj
    public int curAdj;          // Current OOM adjustment for this process 当前正在计算的adj,这是curRawAdj被maxAdj削平的值
    int setAdj;                 // Last set OOM adjustment for this process 上次计算的curAdj设置到lowmemorykiller系统后的adj
    int verifiedAdj;            // The last adjustment that was verified as actually being set

    //和调度优先级有关
    int curSchedGroup;          // Currently desired scheduling class
    int setSchedGroup;          // Last set to background scheduling class
    int vrThreadTid;            // Thread currently set for VR scheduling

    //回收内存级别
    //默认是80%,ComponentCallbacks2.TRIM_MEMORY_COMPLETE
    int trimMemoryLevel;        // Last selected memory trimming level

    //判断该进程的状态,主要和其中运行的Activity,Service有关  ActivityManager.PROCESS_STATE

    public int curProcState = PROCESS_STATE_NONEXISTENT; // Currently computed process state
    int repProcState = PROCESS_STATE_NONEXISTENT; // Last reported process state
    int setProcState = PROCESS_STATE_NONEXISTENT; // Last set process state in process tracker
    int pssProcState = PROCESS_STATE_NONEXISTENT; // Currently requesting pss for
    int savedPriority;          // Previous priority value if we're switching to non-SCHED_OTHER
    int renderThreadTid;        // TID for RenderThread
    boolean serviceb;           // Process currently is on the service B list
    boolean serviceHighRam;     // We are forcing to service B list due to its RAM use
    boolean notCachedSinceIdle; // Has this process not been in a cached state since last idle?
    boolean hasClientActivities;  // Are there any client services with activities?
    boolean hasStartedServices; // Are there any started services running in this process?
    boolean foregroundServices; // Running any services that are foreground?
    boolean foregroundActivities; // Running any activities that are foreground?
    boolean repForegroundActivities; // Last reported foreground activities.
   //这个表示进程是否绑定的activity,通过activities.size的值和visible来判断,如果visible=true,就是false
    boolean systemNoUi;         // This is a system process, but not currently showing UI.
    boolean hasShownUi;         // Has UI been shown in this process since it was started?
    //显示顶层的ui
    boolean hasTopUi;           // Is this process currently showing a non-activity UI that the user
                                // is interacting with? E.g. The status bar when it is expanded, but
                                // not when it is minimized. When true the
                                // process will be set to use the ProcessList#SCHED_GROUP_TOP_APP
                                // scheduling group to boost performance.
    boolean hasOverlayUi;       // Is the process currently showing a non-activity UI that
                                // overlays on-top of activity UIs on screen. E.g. display a window
                                // of type
                                // android.view.WindowManager.LayoutParams#TYPE_APPLICATION_OVERLAY
                                // When true the process will oom adj score will be set to
                                // ProcessList#PERCEPTIBLE_APP_ADJ at minimum to reduce the chance
                                // of the process getting killed.
    boolean pendingUiClean;     // Want to clean up resources from showing UI?
    boolean hasAboveClient;     // Bound using BIND_ABOVE_CLIENT, so want to be lower
    boolean treatLikeActivity;  // Bound using BIND_TREAT_LIKE_ACTIVITY

    //判断该进程的状态,主要和其中运行的Activity,Service有关
    boolean bad;                // True if disabled in the bad process list  是否处于系统BadProcess列表
    public boolean killedByAm;  // True when proc has been killed by activity manager, not for RAM//当值为true,意味着该进程是被AMS所杀,而非由于内存低而被LMK所杀
    public boolean killed;      // True once we know the process has been killed//进程被杀死
    boolean procStateChanged;   // Keep track of whether we changed 'setAdj'.
    boolean reportedInteraction;// Whether we have told usage stats about it being an interaction
    boolean unlocked;           // True when proc was started in user unlocked state
    long interactionEventTime;  // The time we sent the last interaction event
    long fgInteractionTime;     // When we became foreground for interaction purposes
    public String waitingToKill; // Process is waiting to be killed when in the bg, and reason
    Object forcingToImportant;  // Token that is forcing this process to be important

    //序号,每次调节进程优先级或者LRU列表位置时,这些序号都会递增
    int adjSeq;                 // Sequence id for identifying oom_adj assignment cycles
    int lruSeq;                 // Sequence id for identifying LRU update cycles
    CompatibilityInfo compat;   // last used compatibility mode
    IBinder.DeathRecipient deathRecipient; // Who is watching for the death.
    //activity正在运行
    ActiveInstrumentation instr;// Set to currently active instrumentation running in process
    boolean usingWrapper;       // Set to true when process was launched with a wrapper attached
    final ArraySet<BroadcastRecord> curReceivers = new ArraySet<BroadcastRecord>();// receivers currently running in the app
    long whenUnimportant;       // When (uptime) the process last became unimportant
    long lastCpuTime;           // How long proc has run CPU at last check
    long curCpuTime;            // How long proc has run CPU most recently
    long lastRequestedGc;       // When we last asked the app to do a gc
    long lastLowMemory;         // When we last told the app that memory is low
    long lastProviderTime;      // The last time someone else was using a provider in this process.
    boolean reportLowMemory;    // Set to true when waiting to report low mem
    boolean empty;              // Is this an empty background process?
    boolean cached;             // Is this a cached process?
    String adjType;             // Debugging: primary thing impacting oom_adj.
    int adjTypeCode;            // Debugging: adj code to report to app.
    Object adjSource;           // Debugging: option dependent object.
    int adjSourceProcState;     // Debugging: proc state of adjSource's process.
    Object adjTarget;           // Debugging: target component impacting oom_adj.
    Runnable crashHandler;      // Optional local handler to be invoked in the process crash.

    // all activities running in the process
    final ArrayList<ActivityRecord> activities = new ArrayList<>();
    // all ServiceRecord running in this process
    final ArraySet<ServiceRecord> services = new ArraySet<>();
    // services that are currently executing code (need to remain foreground).
    final ArraySet<ServiceRecord> executingServices = new ArraySet<>();
    // All ConnectionRecord this process holds
    final ArraySet<ConnectionRecord> connections = new ArraySet<>();
    // all IIntentReceivers that are registered from this process.
    final ArraySet<ReceiverList> receivers = new ArraySet<>();
    // class (String) -> ContentProviderRecord
    //保持provider
    final ArrayMap<String, ContentProviderRecord> pubProviders = new ArrayMap<>();
    // All ContentProviderRecord process is using
    final ArrayList<ContentProviderConnection> conProviders = new ArrayList<>();
    //有相关的class运行在这个进程中
    String isolatedEntryPoint;  // Class to run on start if this is a special isolated process.
    String[] isolatedEntryPointArgs; // Arguments to pass to isolatedEntryPoint's main().

    boolean execServicesFg;     // do we need to be executing services in the foreground?
    boolean persistent;         // always keep this application running?//经常不被杀死,杀死也会被系统重新启动
    boolean crashing;           // are we in the process of crashing?
    Dialog crashDialog;         // dialog being displayed due to crash.
    boolean forceCrashReport;   // suppress normal auto-dismiss of crash dialog & report UI?
    boolean notResponding;      // does the app have a not responding dialog?
    Dialog anrDialog;           // dialog being displayed due to app not resp.
    boolean removed;            // has app package been removed from device?
    boolean debugging;          // was app launched for debugging?
    boolean waitedForDebugger;  // has process show wait for debugger dialog?
    Dialog waitDialog;          // current wait for debugger dialog

    String shortStringName;     // caching of toShortString() result.
    String stringName;          // caching of toString() result

ProcessRecord 记录了进程的所有信息,比如进程名,进程包的activity ,service以及oom的阈值等有关进程的信息,具体可以看上面的代码块,有关此类的介绍可以看这篇博文:https://blog.csdn.net/tonyandroid1984/article/details/70224827

2.3 Process

// frameworks/base/core/java/android/os/Process.java
 public static final int THREAD_PRIORITY_DEFAULT = 0;

    /*
     * ***************************************
     * ** Keep in sync with utils/threads.h **
     * ***************************************
     */

    /**
     * Lowest available thread priority.  Only for those who really, really
     * don't want to run if anything else is happening.
     * Use with {@link #setThreadPriority(int)} and
     * {@link #setThreadPriority(int, int)}, <b>not</b> with the normal
     * {@link java.lang.Thread} class.
     */
    public static final int THREAD_PRIORITY_LOWEST = 19;

    /**
     * Standard priority background threads.  This gives your thread a slightly
     * lower than normal priority, so that it will have less chance of impacting
     * the responsiveness of the user interface.
     * Use with {@link #setThreadPriority(int)} and
     * {@link #setThreadPriority(int, int)}, <b>not</b> with the normal
     * {@link java.lang.Thread} class.
     */
    public static final int THREAD_PRIORITY_BACKGROUND = 10;

    /**
     * Standard priority of threads that are currently running a user interface
     * that the user is interacting with.  Applications can not normally
     * change to this priority; the system will automatically adjust your
     * application threads as the user moves through the UI.
     * Use with {@link #setThreadPriority(int)} and
     * {@link #setThreadPriority(int, int)}, <b>not</b> with the normal
     * {@link java.lang.Thread} class.
     */
    public static final int THREAD_PRIORITY_FOREGROUND = -2;

    /**
     * Standard priority of system display threads, involved in updating
     * the user interface.  Applications can not
     * normally change to this priority.
     * Use with {@link #setThreadPriority(int)} and
     * {@link #setThreadPriority(int, int)}, <b>not</b> with the normal
     * {@link java.lang.Thread} class.
     */
    public static final int THREAD_PRIORITY_DISPLAY = -4;

    /**
     * Standard priority of the most important display threads, for compositing
     * the screen and retrieving input events.  Applications can not normally
     * change to this priority.
     * Use with {@link #setThreadPriority(int)} and
     * {@link #setThreadPriority(int, int)}, <b>not</b> with the normal
     * {@link java.lang.Thread} class.
     */
    public static final int THREAD_PRIORITY_URGENT_DISPLAY = -8;

    /**
     * Standard priority of audio threads.  Applications can not normally
     * change to this priority.
     * Use with {@link #setThreadPriority(int)} and
     * {@link #setThreadPriority(int, int)}, <b>not</b> with the normal
     * {@link java.lang.Thread} class.
     */
    public static final int THREAD_PRIORITY_AUDIO = -16;

    /**
     * Standard priority of the most important audio threads.
     * Applications can not normally change to this priority.
     * Use with {@link #setThreadPriority(int)} and
     * {@link #setThreadPriority(int, int)}, <b>not</b> with the normal
     * {@link java.lang.Thread} class.
     */
    public static final int THREAD_PRIORITY_URGENT_AUDIO = -19;

    /**
     * Minimum increment to make a priority more favorable.
     */
    public static final int THREAD_PRIORITY_MORE_FAVORABLE = -1;

    /**
     * Minimum increment to make a priority less favorable.
     */
    public static final int THREAD_PRIORITY_LESS_FAVORABLE = +1;

    /**
     * Default scheduling policy
     * @hide
     */
    //以下就是进程创建的调度策略
    public static final int SCHED_OTHER = 0;

    /**
     * First-In First-Out scheduling policy
     * @hide
     */
    public static final int SCHED_FIFO = 1;

    /**
     * Round-Robin scheduling policy
     * @hide
     */
    public static final int SCHED_RR = 2;

    /**
     * Batch scheduling policy
     * @hide
     */
    public static final int SCHED_BATCH = 3;

    /**
     * Idle scheduling policy
     * @hide
     */
    public static final int SCHED_IDLE = 5;

    //paid,tid 的获取
    public static final int myPid() {
        return Os.getpid();
    }

    /**
     * Returns the identifier of this process' parent.
     * @hide
     */
    public static final int myPpid() {
        return Os.getppid();
    }

    /**
     * Returns the identifier of the calling thread, which be used with
     * {@link #setThreadPriority(int, int)}.
     */
    public static final int myTid() {
        return Os.gettid();
    }

    /**
     * Returns the identifier of this process's uid.  This is the kernel uid
     * that the process is running under, which is the identity of its
     * app-specific sandbox.  It is different from {@link #myUserHandle} in that
     * a uid identifies a specific app sandbox in a specific user.
     */
    public static final int myUid() {
        return Os.getuid();
    }

  //设置线程等级,也就是更大的可能获得cpu调度的时间。
    public static final native void setThreadPriority(int tid, int priority)
            throws IllegalArgumentException, SecurityException;

    public static final native void setThreadPriority(int priority)
            throws IllegalArgumentException, SecurityException;

    //设置线程的调度等级和策略,等级有-20到19  策略有SCHED_OTHER,SCHED_FIFO,SCHED_RR
    public static final native void setThreadScheduler(int tid, int policy, int priority)
            throws IllegalArgumentException;

    //group == THREAD_GROUP_FOREGROUND
    public static final native void setProcessGroup(int pid, int group)
            throws IllegalArgumentException, SecurityException;

    /**
     * Return the scheduling group of requested process.
     *
     * @hide
     */
    public static final native int getProcessGroup(int pid)
            throws IllegalArgumentException, SecurityException;

以上的是代码块并没有包含全部的类信息,只是挑选一些比较重要的字段和函数来说明。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 219,589评论 6 508
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,615评论 3 396
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 165,933评论 0 356
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,976评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,999评论 6 393
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,775评论 1 307
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,474评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,359评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,854评论 1 317
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,007评论 3 338
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,146评论 1 351
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,826评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,484评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,029评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,153评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,420评论 3 373
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,107评论 2 356

推荐阅读更多精彩内容