源码阅读--进程管理
来源:互联网 发布:中指数据怎样批量下载 编辑:程序博客网 时间: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对象死亡通知机制
- 源码阅读--进程管理
- nginx 源码分析阅读笔记-进程管理
- ril进程源码阅读札记
- android源码阅读-----zygote进程
- Memcached内存管理源码阅读
- [Chrome源码阅读] 理解Browser进程
- [Chrome源码阅读] 理解Browser进程
- Nginx源码阅读(进程间通信)
- 内核源码阅读(一)进程
- 内核源码阅读(二)进程复制
- 内核源码阅读(四)进程ID
- 内核源码阅读(五)进程ID
- chromium源码阅读--进程的Message Loop
- XV6源代码阅读--进程与内存管理
- Memcache源码阅读(4)---内存管理
- Memcache源码阅读(5)---哈希表管理
- Nginx 源码阅读笔记3 时间管理
- skynet底层源码阅读(3)-模块管理
- 细说mysql索引
- Mac 下搭建XAMPP
- /bin,/sbin,/usr/sbin,/usr/bin 目录
- 数据库(分库分表)中间件对比
- Axure RP 8 注册码(最新亲测可用)
- 源码阅读--进程管理
- 新能源整车控制器VCU开发过程分享
- Spring Cloud构建微服务架构:服务网关(基础)
- 多线程下载
- Bulls and Cows问题及解法
- 定义自定义表值函数(split),用于分隔字符串
- String,StringBuffer与StringBuilder的区别?
- WebView使用
- java中Object默认的基本方法