源码阅读--进程管理

本文深入剖析了Android应用启动过程中的关键环节,包括进程创建、进程优先级与回收机制及Binder死亡通知机制等。通过详细的技术步骤揭示了Activity启动时应用进程的创建方式,以及系统如何管理和回收进程。

应用进程的创建

Activity启动中应用进程的创建中从应用Activity启动的总体过程分析了Activity所在进程的创建以及应用与AMS绑定过程。
在要启动的应用组件所属的进程没有创建时,会先创建对应进程,先在AMS的mProcessNames中查找ProcessRecord记录,没有的话会创建新的ProcessRecord,并添加到mProcessNames,然后调用Process.start创建进程。
进程的具体创建过程如下:

这里写图片描述

1.打开与Zygote进程之间的Socket通信连接,所有的应用进程都是Zygote进程fork产生的。向Zygote进程发送启动进程参数
2.Zygote进程接收到命令和参数后,创建ZygoteConnection对象,并执行runOnce方法,最终调用系统调用fork创建新的进程。
3.在进程创建后,ZygoteConnection会调用handleChildProc方法,执行RuntimeInit的zygoteInit方法,继续执行applicationInit方法,这里触发了ActivityThread的main方法,应用客户端正式开始启动。

AMS与Zygote进程间的通信

AMS与Zygote进程间的通信使用了Unix-domain Socket,在代码中使用LocalSocket和LocalServerSocket实现,这是不同于Binder的另一种进程间通信方式。详细可参考参考资料
Unix-domain Socket在socketApi使用上与普通的网络socket类似,熟悉socket的都知道,服务端需要在指定端口上监听客户端的连接请求。在Zygote进程启动之后会在main方法中调用如下的一个方法–runSelectLoop

/frameworks/base/core/java/com/android/internal/os/ZygoteInit.java这里写图片描述

这里写图片描述

这里用到了poll机制,这是一种多路复用机制,暂时理解为通过轮询判断是否有socket连接请求。当有请求到来时调用了acceptCommandPeer方法创建了ZygoteConnection。

App的程序入口ActivityThread

前面的分析最后在RuntimeInit中调用了invokeStaticMain方法触发ActivityThread的main方法

这里写图片描述

这里使用反射机制调用了一个类的静态方法main,怎么确定这个类是ActivityTread。看这个方法是在哪调用的

这里写图片描述

下面是对参数的解析

这里写图片描述

startClass参数不是以”–”开头的,且是第一个不以”–”开头的。再看参数发送代码,在Process类的startViaZygote方法,只截取一段

这里写图片描述

这里的processClass是Process.start的第一个参数。再看下面这段
这里写图片描述
ok,入口确实就是ActivityThread的main函数。

进程优先级与进程回收

当我们退出应用(返回键)的时候,系统并不会销毁对应的应用进程,当系统内存不足(这里的内存不足和GC时的内存不足是两个概念)时,Low Memory Killer 会根据进程的优先级以及内存使用情况回收进程资源。
Android使用oom_adj(OOM adjustment)标记进程优先级,在ProcessList类中定义了几类oom_adj级别

这里写图片描述

可以看出值越大对应的进程越可能先被回收,优先级也就越低;但是LMK的回收处理只划分了6个级别,不可能一一对应上面的级别划分,使用到的级别有下面这些
1、前台进程
2、可见进程
3、可感知进程(服务进程)
4、正在备份的进程
5、后台进程
6、空进程

这里写图片描述

mOomMinFreeLow(512M内存)和 mOomMinFreeHigh(1G内存)定义了每个级别进程回收的内存下限:当内存小于49152kB时可以回收oom_adj值大于CACHE_APP_MAX_ADJ的进程,以此类推;这两个成员只是参考值;真正的限制是在mOomMainFree中设置的;ProcessList的updateOomLevels方法计算并设置具体的回收内存门限值。

设置进程优先级

LMK是系统内核实现的,AMS只需要更新oom_adj的值,在AMS中提供了方法updateOomAdjLocked来更新进程的优先级。

计算oom_adj computeOomAdjLocked

1.maxAdj;Maximum OOM adjustment for this process
进程adj上限,优先级下限;
2.FOREGROUND_APP_ADJ:TOP_APP、instrumentationClass、isReceivingBroadcast、executingServices。
3.遍历进程中所有的Activity,activity可见adj设为VISIABLE _APP:activity.isVisible;pausing、paused、stopping为用户可感知。
4.拥有foregroundService或forcingToForeground设为用户可感知。
5.mHeavyWeightProcess、mHomeProcess、mPreviousProcess分别设置对应adj级别。
6.遍历所有的Service,计算所有依赖本进程服务的进程的adj值clientAdj,更新本进程Adj。
7.遍历所有的Provider,计算所有依赖本进程的进程的adj,更新本进程Adj。
以上计算的到的adj值是原始值,包括前面列出的所有的adj级别,在ProcessRecord中对应curRawAdj。但是LMK对应只有6个级别,每个adj都要对应到这6个级别,在ProcessRecord中对应curAdj;ProcessRecord的方法modifyRawOomAdj提供了转换功能:

这里写图片描述

AMS回收进程

在系统内存不足时,LMK会根据进程优先级回收相应的进程资源,AMS中特定情况下也会杀死进程。Process类提供了killProcess和killProcessQuiet方法。
这里写图片描述

/frameworks/base/core/jni/android_util_Process.cpp
这里写图片描述

这里使用了系统回调kill杀死进程。kill参考Linux 下的KILL函数的用法
在LMK中同样调用了kill函数杀死进程,/system/core/lmkd/lmkd.c
这里写图片描述

Binder死亡通知机制

进程回收之后,AMS如何知道客户端进程已经死亡了,首先考虑AMS和客户端进程是如何通信的,ok ,Binder机制,binder机制提供了一种死亡通知机制,具体可以看参考资料。
在AMS中定义了一个内部类

这里写图片描述

在attachApplicationLocked中使用了该类
这里写图片描述
也就是在客户端关联到AMS时就会注册死亡通知。

参考资料

Unix domain socket
Android Low Memory Killer
Android 6.0的lowmemorykiller机制
Binder对象死亡通知机制

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值