Android 进程学习

一、Android 进程

  1. 默认情况下,同一个APP的所有组件都运行在相同的进程中(但可以通过在清单文件中配置某些组件所属的进程)
  2. 内存不足的情况下,Android 系统会想着kill 某个进程来释放该进程的内存来给其他为用户提供更紧急的服务的进程使用
  3. 在关闭的进程中的运行的组件会随着进程的关闭随之关闭
  4. 决定kill 哪个进程时,Android 系统会权衡所有进程对用户的相对重要程度。例如:相对于托管可见 Activity 的进程而言,更有可能 kill 托管不可见 Activity 的进程。因此,是否终止 kill 某个进程取决于该进程中所运行组件的状态

二、Android系统中存在的进程

1. Zygote进程
·Zygote,受精卵的意思。在Android系统中,所有的系统服务进程SystemServer以及应用程序进程都是由Zygote进程Fork(孕育)出来的。
2. App主进程
·每一个App都是运行在一个独立的进程中;
·这个进程也是由Zygote进程Fork出来的;
·App的进程的名称就是包名,并由AMS(ActivityManagerService)管理,BroadcastReceiver的发送也是由AMS来完成的。
3. App辅助进程
·一个App可以拥有多个进程;
·具体为在AndroidManifest.xml文件中为Activity或者Service进行配置android:process="";
·辅助进程也是由Zygote Fork出来并由AMS管理
4. Native进程
·Android程序运行在Dalvik虚拟机中;
·NDK允许用户使用类似C / C++之类的原生代码语言执行部分程序;
·由NDK所Fork出的进程称之为Native进程;
·Native进程自由度较高可以不受AMS管理;
·NDK也可用来做进程保活;

三、Android系统中进程的优先级

  1. Android系统中进程的优先级定义在com.android.server.am.ProcessList 类中,这个类在SDK中可以找到;
  2. 在 LMS 回收内存时会根据进程的级别优先杀死 OOM_ADJ 比较大的进程,对于优先级相同的进程则进一步受到进程所占内存和进程存活时间的影响;
  3. 主要优先级定义(oom_adj值)
    (1)oom_adj >= 4,比较容易被kill的进程
    (2)4> oom_adj >= 0,不容易被kill的Android进程
    (3)oom_adj < 0 ,Linux进程,非安卓进程

名称

说明

UNKNOWN_ADJ = 16

预留最低级别,一般指将要会缓存进程,无法获取确定值

CACHED_APP_MAX_ADJ = 15

持有不可见的Activity的进程,也就是后台进程,系统内存不足会被Kill

CACHED_APP_MIN_ADJ = 9

缓存进程,也就是空进程

SERVICE_B_ADJ = 8

SERVICE_B_ADJ = 8

PREVIOUS_APP_ADJ = 7

切换进程,切换应用程序时保存的之前的进程,上一个App的进程

HOME_APP_ADJ = 6

与Home交互的进程

SERVICE_ADJ = 5

包含Service的进程,一般来说Kill掉对用户影响不太大

HEAVY_WEIGHT_APP_ADJ = 4

高权重进程,在后台运行但是系统尽量不Kill掉

BACKUP_APP_ADJ = 3

托管备份的进程,Kill掉是一个bad idea值

PERCEPTIBLE_APP_ADJ = 2

可被用户感知的进程,比如音乐播放器

VISIBLE_APP_ADJ = 1

可见进程(Visible process),但不一定都是前台进程,有可能是被覆盖的Activity

FOREGROUND_APP_ADJ = 0

前台进程,运行在前台的App的进程

PERSISTENT_SERVICE_ADJ = -11

重要进程,系统或重要进程绑定的进程

PERSISTENT_PROC_ADJ = -12

核心进程,系统持续进程,如电话

SYSTEM_ADJ = -16

系统进程

NATIVE_ADJ = -17

不由系统管理的Native相关进程

  1. 查看进程优先级
//oom_adj的值就是进程的优先级
  //查看oom_adj值
  cat /proc/${pid}/oom_adj

四、Android系统中常见的进程(优先级从高到低排列)

  1. List 前台进程(Foreground process)
    用户当前操作的进程,一个进程满足以下任一条件 ,即视为前台进程:
    (1)进程持有一个正与用户交互的Activity
    (2)进程持有一个满足以下条件的Service:
    ·与正在交互的Activity绑定
    ·使用startForeground()启动的前台服务
    ·Service正在执行生命周期函数,onCreate(), onStart(), or onDestroy()
    (3)进程持有一个正在执行onReceive()的BroadcastReceiver
  2. 可见进程(Visible process)
    (1)进程持有一个可见的Activity,比如被Dialog遮挡进入onPause()状态的Activity
    (2)进程持有一个和可见的(或前台的)Activity 绑定的Service
  3. 服务进程(Service process)
    (1)进程持有一个使用startService()开启的服务,且不属于以上两种优先级比较高的Service,被视为服务进程。比如下载文件、后台播放音乐
  4. 后台进程(Background process)
    (1)进程持有不可见的,调用了onStop()但是没有调用onDestroy()的Activity,被认为是后台进程。这样做的原因是保存一些Activity用于用户选择和跳转。它们会被保存在一个LRU (least recently used)列表中,系统内存不足时可能会Kill掉最早的Activity,可以通过重写onSaveInstanceState()在被Kill之前来保存数据.
  5. 空进程
    (1)进程中不包含活跃的组件,被认为是空进程;保存这种进程的原因是缓存需要。

五、提高进程优先级

(1)AndroidManifest.xml中配置android:persistent=“true”;
(2)在Service中开启线程做耗时操作,会被判断为服务进程;
(3)startForeground()启动前台服务,需使用stopForeground()关闭;
(4)与NotificationManager交互,让进程变成可感知进程;
(5)使用广播,避免成为空进程;
(6)使用Native进程做进程保活;

六、Android中进程可能被杀死的情况

进程杀死场景

调用接口

可能影响范围

触发系统进程管理机制

Lowmemorykiller

从进程importance值由大到小依次杀死,释放内存

被第三方应用杀死(无Root)

killBackgroundProcess

只能杀死oom_adaj为4以上的进程

被第三方应用杀死(有Root)

force-stop或者kill

理论上可以杀死所有进程,一般只杀死非系统和非前台和可见进程

厂商杀进程功能

force-stop或者kill

理论上可以杀死所有进程,包括Native进程

用户主动强行停止进程

force-stop

只能停用第三方和非system、phone进程应用(停用system进程应用会造成Android重启

七、进程间的通信

(1)进程间的通信(IPC,Inter-Process Communication)是指至少两个进程之间传递数据或者信号的一些技术或方法;
(2)对于程序而言,IPC属于一组编程接口,让程序员能够协调不同的进程,使之能在一个操作系统里同时运行,并相互传递、交换信息,使得一个程序能够在同一个时间处理许多用户的需求
(3)进程间通信的必要性:
·Android系统为了保证应用数据的安全性,应用程序之间是不能共享内存的,各个应用程序的数据是独立的。
·在实际使用中,难免会产生应用之间共享数据的需求,所以就需要运用进程间通信的机制来实现各个应用之间的数据共享。
(4)Android中几种常见的进程间的通信
·Android中的ALDI就是一种RPC框架

名称

优点

缺点

使用场景

Bundle

简单易用(使用Key Value的形式)简单

只能传输Bundle支持的数据类型

四大组件间的进程间通信

文件共享

简单易用(各个应用只需要读写同一个文件即可)

不适用高并发场景,并且无法做到进程间即时通信

不适用高并发场景,并且无法做到进程间即时通信

AIDL

功能强大,支持一对多实时并发通信

使用稍复杂,需要处理好线程间的关系;不能传输数据量较大的数据

一对多通信且有RPC需求

Messenger

功能一般,支持一对多串行通信,支持实时通信

不能很好地处理高并发的情形,不支持RPC,由于数据通过Message传输,因此只能传输Bundle支持的数据类型

低并发的一对多实时通信,无RPC需求,或者无需要返回结果的RPC需求

ContentProvider

支持一对多的实时并发通信,在数据源共享方面功能强大,可通过Call方法扩展其它操作

可以理解为受约束的AIDL,主要提供对数据源的CRUD操作

一对多的进程间数据共享

BroadcastReceiver

操作简单,支持一对多实时通信

只支持数据单向传递,效率低且安全性不高

一对多的低频率单向通信

Socket

功能强大,可通过网络传输字节流,支持一对多实时并发通信

实现细节步骤稍繁琐,不支持直接的RPC

网络间的数据交换