zoukankan      html  css  js  c++  java
  • android里面的进程回收机制[转载]

    http://blog.sina.com.cn/s/blog_40d475e901012jgt.html

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

    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值越高代表该进程优先级越低. Init.rc中:
    • 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:
    查看本机设置:
    cat /sys/module/lowmemorykiller/parameters/adj
    0,1,2,7,14,15

    回收时机:
    Init.rc中:
    •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.

    更新oom_adj的值:

    在ComputeOomAdjLocked中计算出进程的oom_adj,例如:
    if (app == TOP_APP) {
    // The last app on the list is the foreground app.
    adj = FOREGROUND_APP_ADJ;
    app.adjType = "top-activity";
    }

    Android kernel中的low memory killer
    Android的Low Memory Killer根据需要(当系统内存短缺时)杀死进程释放其内存,源代码在
    kernel/drivers/misc/lowmemorykiller.c
    简单说就是寻找一个最合适的进程杀死,从而释放它占用的内存.
    最合适:
    •oom_adj越大
    •占用物理内存越多

    一旦一个进程被选中,内核会发送SIGKILL信号将之杀死.
    for_each_process(p) {
    ……
    if(selected == NULL || p->oomkilladj > selected->oomkilladj ||
    (p->oomkilladj == selected->oomkilladj &&
    tasksize > selected_tasksize))
    {
    selected = p;
    }
    }
    if(selected != NULL) {
    force_sig(SIGKILL, selected);
    }

    查看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的等级高。
    按back键使得进程中的activity在后台运行而不是destory,需重载back按键(没有任何activity在运行的进程优先被杀).
    依赖于其他优先级高的进程.

    强制修改进程属性:
    •在程序中设置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

    转自http://blog.sina.com.cn/s/blog_514048cb0100wi2j.html

  • 相关阅读:
    Linux下sed,awk,grep,cut,find学习笔记
    Python文件处理(1)
    KMP详解
    Java引用详解
    解决安卓中页脚被输入法顶起的问题
    解决swfupload上传控件文件名中文乱码问题 三种方法 flash及最新版本11.8.800.168
    null id in entry (don't flush the Session after an exception occurs)
    HQL中的Like查询需要注意的地方
    spring mvc controller间跳转 重定向 传参
    node to traverse cannot be null!
  • 原文地址:https://www.cnblogs.com/fireflyxml/p/3921712.html
Copyright © 2011-2022 走看看