源码阅读--进程管理

来源:互联网 发布:中指数据怎样批量下载 编辑:程序博客网 时间:2024/05/17 08:31

应用进程的创建

在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对象死亡通知机制

原创粉丝点击