启动进程
启动新应用程序进程的流程.png1> 某个现有进程调用活动管理器,发出意图,描述它想启动的新活动;
2> 活动管理器要求包管理器将这个意图解析为一个明确的组件;
3> 活动管理器判断这个应用程序的进程未运行,然后向zygote请求一个具有合适UID的新进程;
4> zygote运行fork指令,克隆自己来创造一个新进程,下方权限并配置新进程的UID和沙箱,初始化该进程的Dalvik,使得Java runtime开始完全执行。例如启动垃圾收集等线程。
5> 新进程如今是一个zygote的克隆,并运行着完全配置好的Java环境,它回调活动管理器,询问后者“我该做什么”;
6> 活动管理器返回即将启动的应用程序的完整信息,如源码位置等;
7> 新进程读取应用程序的源码,开始运行;
8> 活动管理器将所有即将进行的操作发送给新进程,在此处为“启动特定活动”;
9> 新进程收到指令,启动活动,实例化合适的Java类并执行;
说明:当准备启动启动活动时,应用程序的进程可能已经存在,此时活动管理器会直接跳到末尾,向该进程发送一条新指令,让它实例化并执行合适的组件。
进程生命周期
活动管理器记录每个进程中运行的所有活动、服务、接收器和内容提供者,据此判断该进程的重要程度,判断何时进程不再被需要。
回想Android内核中的内存溢出强制结束指令,使用一个进程的oom_adj进行严格排序,决定哪个进程需要优先强制结束。活动管理器基于每个进程的状态,通过将其归类为几个主要用途,从而合理设定其oom_adj。如下图所示,按重要程度从高到低排序:
类别 | 描述 | oom_adj |
---|---|---|
SYSTEM | 系统和守护进程 | -16 |
PERSISTENT | 总在运行的应用程序进程 | -12 |
FOREGROUND | 正在与用户交互 | 0 |
VISIBLE | 用户可见 | 1 |
PERCEPTIBLE | 用户可感知 | 2 |
SERVICE | 正在运行的服务 | 3 |
HOME | 主界面 | 4 |
CACHED | 未被使用的进程 | 5 |
当RAM内存不足时,使得内存溢出强制结束命令优先中止缓存(cached)类别的进程,尝试重新获得足够的所需内存,随后中止主界面(home)类别,服务(service)类别,以此类推。在同一个oom_adj水平中,它将优先中止内存占用较大的进程。
进程依赖性
进程之间的依赖性可能发生在内容提供器上或是服务上,无论哪种情况,操作系统必须记录这些依赖性,并合理管理这些进程。例如相机应用程序中照片通过内容提供器允许其它应用发问这些图片,成为相机应用程序的客户。进程依赖性产生两个关键事实:何时创建进程以及进程内部的组件,进程的oom_adj重要程度值得设定。以相机应用程序为例,它的进程和它的内容提供器并不是总在运行的,当某个其他应用程序需要访问它的内容提供器时才会被创建。当相机的内容提供器被访问时,相机进程会被认为至少具有与使用它的应用程序同等的重要程度。
为了计算每个进程的最终重要程度,系统需要维护进程之间的依赖图。每个进程都有其中正在运行的服务和内容提供器列表,而每个服务与内容提供器则有正在使用它的其他进程列表。遍历一个进程的依赖图时,需要遍历该进程的所有服务和内容提供器,以及使用这些服务和内容提供器的所有其他进程。如下表所示:
进程 | 状态 | 重要程度 |
---|---|---|
system | 操作系统核心部分 | SYSTEM |
phone | 为实现电话功能而总在运行 | PERSISTENT |
当前前景应用程序 | FOREGROUND | |
camera | 因需要加载附件而被电子邮件应用程序使用 | FOREGROUND |
music | 运行背景服务播放音乐 | PERCEPTIBLE |
media | 因需要访问用户音乐而被音乐应用程序使用 | PERCEPTIBLE |
download | 正在为用户下载文件 | SERVICE |
launcher | 应用程序启动器,未被使用 | HOME |
maps | 先前使用过的地图应用程序 | CACHED |
参考资料:
[1] 现代操作系统
网友评论