zoukankan      html  css  js  c++  java
  • Android的进程优先级与进程回收详解

    android 检测碰撞 汇总
    http://www.eoeandroid.com/thread-203518-1-1.html

    Android 3D特效源码汇总
    http://www.eoeandroid.com/thread-203549-1-1.html

    模仿朋友网左右推出菜单【升级版】
    http://www.eoeandroid.com/thread-203620-1-1.html

    Android中的进程是托管的,当系统进程空间紧张的时候,会依照优先级自动进行进程的回收.
    由此带来三个问题:
    回收规则: 什么时候回收与回收哪一个
    避免误杀: 如何阻止被回收
    数据恢复与保存: 被回收了怎么办

    Android将进程分为6个等级,它们按优先级顺序由高到低依次是:
    1.前台进程( FOREGROUND_APP)
    2.可视进程(VISIBLE_APP )
    3. 次要服务进程(SECONDARY_SERVER )
    4.后台进程 (HIDDEN_APP)
    5.内容供应节点(CONTENT_PROVIDER)
    6.空进程(EMPTY_APP)

    特征
    1.如果一个进程里面同时包含service和可视的activity,那么这个进程应该归于可视进程,而不是service进程.
    2.另外,如果其他进程依赖于它的话,一个进程的等级可以提高.例如,一个A进程里的service被绑定到B进程里的组件上,进程A将总被认为至少和B进程一样重要.
    3.系统中的phone服务被划分到前台进程而不是次要服务进程.

    在android中以进程的oom_adj值也就代表了它的优先级.

    oom_adj值越高代表该进程优先级越低.
    adb shell cat /proc/<pid>/oom_adj 查看某个进程当前的oom_adj值

    进程oom_adj值的更新:
    android进程的oom_adj都在ActivityManagerService中更新

    updateOomAdjLocked() =>
    int adj = computeOomAdjLocked(app, hiddenAdj, TOP_APP, false);[/font]
    Process.setOomAdj(app.pid, adj) =>[/font]
    android_os_Process_setOomAdj [color=lime]//android_util_Process.cpp

    进程回收lowmemorykiller:
    参考lowmemorykiller.c 的lowmem_shrink函数,计算哪些进程该回收,并发送SIGKILL信号将该进程KILL。

        if (selected) {
            lowmem_print(1, "send sigkill to %d (%s), adj %d, size %d\n",
                     selected->pid, selected->comm,
                     selected_oom_adj, selected_tasksize);
            lowmem_deathpending = selected;
            lowmem_deathpending_timeout = jiffies + HZ;
            force_sig(SIGKILL, selected);
    
            nr_samples--;
            rem -= selected_tasksize;
        }

    oom_adj等级设置在init.rc中:

    # Define the memory thresholds at which the above process classes will
    # be killed.  These numbers are in pages (4k).
        setprop ro.FOREGROUND_APP_ADJ 0
        setprop ro.VISIBLE_APP_ADJ 1
        setprop ro.SECONDARY_SERVER_ADJ 2
        setprop ro.HIDDEN_APP_MIN_ADJ 7
        setprop ro.CONTENT_PROVIDER_ADJ 14
        setprop ro.EMPTY_APP_ADJ 15

    init.rc中,将PID为1的进程(init进程)的oom_adj设置为-16:

        # Set init its forked children's oom_adj.
        write /proc/1/oom_adj -16

    查看本机设置:

    cat /sys/module/lowmemorykiller/parameters/adj
    0,1,2,7,14,15

    回收时机:

    init.rc中:

    # Write value must be consistent with the above properties.
    # Note that the driver only supports 6 slots, so we have combined some of
    # the classes into the same memory level; the associated processes of higher
    # classes will still be killed first.
    setprop ro.FOREGROUND_APP_MEM 1536
    setprop ro.VISIBLE_APP_MEM 2048
    setprop ro.SECONDARY_SERVER_MEM 4096
    setprop ro.HIDDEN_APP_MEM 5120
    setprop ro.CONTENT_PROVIDER_MEM 5632
    setprop ro.EMPTY_APP_MEM 6144

    这些数字也就是对应的内存阈值,一旦低于该值,Android便开始按顺序关闭相应的进程 .

    注意这些数字的单位是page. 1 page = 4 kB.
    上面的六个数字对应的就是(MB): 6,8,16,20,22,24

    查看现在的设置可以:
    cat /sys/module/lowmemorykiller/parameters/minfree
    要想重新设置该值(对应不同的需求):
    echo “1536,2048,4096,5120,15360,23040”>/sys/module/lowmemorykiller/parameters/minfree

    这样当可用内存低于90MB的时候便开始结束空进程. 而当可用内存低于60MB的时候才开始结束内容供应节点.

    具体的回收实现在ActivityManagerService.java中的函数trimApplications()
    1.首先移除package被移走的无用进程.
    2.基于进程当前状态,更新oom_adj值,然后进行以下操作.
    移除没有activity在运行的进程
    如果AP已经保存了所有的activity状态,结束这个AP.
    3.最后,如果目前还是有很多activities 在运行,那么移除那些activity状态已经保存好的activity.


    当系统内存短缺时Android的Low Memory Killer根据需要杀死进程释放其内存
    简单说就是寻找一个最合适的进程杀死,从而释放它占用的内存.
    最合适:
    •oom_adj越大
    •占用物理内存越多

    查看LRU列表:Adb shell dumpsys activity

    当activitydemo在前台时:
    包含Service的进程的优先级比较高,在computeOomAdjLocked
    中将其分为了两小类:

    static final int MAX_SERVICE_INACTIVITY = 30*60*1000; 
    if (now < (s.lastActivity+MAX_SERVICE_INACTIVITY)) {
    if (adj > SECONDARY_SERVER_ADJ) {
    adj = SECONDARY_SERVER_ADJ;
    app.adjType = "started-services";
    app.hidden = false;
    }
    }
    if (adj > SECONDARY_SERVER_ADJ) {
    app.adjType = "started-bg-services";
    }
    }

    完全让进程不被kill是不可能的,我们可以通过一些操作, 使进程被kill的几率变小:
    1 提高进程的优先级:
    后台操作采用Service形式,因为一个运行着service的进程比一个运行着后台activity的等级高。
    2按back键使得进程中的activity在后台运行而不是destory,需重载back按键(没有任何activity在运行的进程优先被杀).
    3依赖于其他优先级高的进程.

    强制修改进程属性:
    在程序中设置setPersistent(true);
    在project的AndroidManifest.xml的<application>中加入属性android:persistent="true"

    android:persistent(SDK)
    Whether or not the application should remain running at all times . The default value is "false". Applications should not normally set this flag; persistence mode is intended only for certain system applications(phone,system).

    1.使用killProcess (int pid)可以杀死指定PID的进程

    public void onClick(View v) { 
    android.os.Process.killProcess(android.os.Process.myPid());
    }

    使用System.exit(0);可以达到同样的效果.

    2.使用finish()可以杀死当前的activity

    1. 保存资料:最好在每次Activity 运行到onPause或
    onStop状态时先保存资料,然后在onCreate时将资
    料读出来(生命周期方法).
    2. OnSaveInstanceState(非生命周期方法)
    onRestoreInstanceState

  • 相关阅读:
    codevs 1115 开心的金明
    POJ 1125 Stockbroker Grapevine
    POJ 2421 constructing roads
    codevs 1390 回文平方数 USACO
    codevs 1131 统计单词数 2011年NOIP全国联赛普及组
    codevs 1313 质因数分解
    洛谷 绕钉子的长绳子
    洛谷 P1276 校门外的树(增强版)
    codevs 2627 村村通
    codevs 1191 数轴染色
  • 原文地址:https://www.cnblogs.com/vus520/p/2706711.html
Copyright © 2011-2022 走看看