攻略大全
1. 粘贴攻略
1.1 应用程序进程启动概述
要想启动一个应用程序,首先要保证这个应用程序所需要的应用程序进程已经启动。
AMS在启动应用程序时会检查这个应用程序需要的应用程序进程是否存在,不存在就会请求Zygote进程启动需要的应用程序进程。
在Zygote的Java框架层中会创建一个Server端的Socket,这个Socket用来等待AMS请求Zygote来创建新的应用程序进程。
Zygote进程通过fork自身创建应用程序进程,这样应用程序进程就会获得Zygote进程在启动时创建的虚拟机实例。
当然,在应用程序进程创建过程中除了获取虚拟机实例外,还创建了Binder线程池和消息循环,这样运行在应用进程中的应用程序就可以方便地使用Binder进行进程间通信以及处理消息了。
2. 造火箭攻略
2.1 流程简述
2.1.1 创建子进程的请求
AMS发起一个创建子进程的请求,在一系列调用中会封装启动应用程序进程所需的参数,并在尝试与Zygote进程的Socket连接时,通过返回的ZygoteState
判断系统能否构建出应用程序进程所需的abi架构。
如果不能构建出所需的abi架构,则直接抛出abi不支持的异常。
如果支持,则将相关所需参数封装进返回的ZygoteState中,并通过ZygoteState.writer(BufferedWriter)
将数据传输到Zygote进程中,而后在zygoteState.inputStream(DataInputStream)
流中等待Zygote进程那边子进程的创建结果Process.ProcessStartResult
的返回(返回的pid标识了结果)并往上回传。
2.1.2 创建子进程的处理
Zygote的main()方法执行时会创建一个Socket等待AMS的请求,并调用runSelectLoop在While死循环中去处理AMS的子进程创建请求。
收到AMS的子进程创建请求后,会读取出相关的数据,通过ZygoteConnection去fork出所需的子进程,并返回一个Runnable对象。
构建子进程的过程中会调用一个native方法用于初始化应用程序进程的binder线程池。
若能无异常fork出子进程,则在最后会返回一个携带了ActivityThread的main反射方法的Runnable对象。
最后调用它的run方法,即执行AcitivityThread的main()方法,至此Zygote进程的创建子进程的处理结束,而应用程序的ActivityThread的main()方法也得到了了执行,即应用程序的主线程mainLooper的消息循环体就此执行。
2.2 流程图示
3. 拧螺丝攻略
3.1 AMS发送启动应用程序进程请求
Zygote接收请求并创建应用程序进程的时序图如图所示。
注意:以上时序图是基于Android 8.0的源码,在Android 11.0中,已改为由ProcessList处理。
3.1.1 AMS请求开启一个进程
3.1.2 AMS的请求交由ProcessList处理
3.1.3 ProcessList的处理
processList会经过一些列内部封装与跳转,最终会看到分别对不同的类型创建出不同类型的进程,从代码的else中看到它调用了Process.start()。
3.1.4 ZygoteProcess的中间处理
如上图所示Process的start方法中只调用了ZygoteProcess的start方法,其中ZygoteProcess类用于保持与Zygote进程的通信状态。该start方法如下所示:
紧接着调用了startViaZygote(),startViaZygote所做处理如下:
它在这将启动应用进程的启动参数保存在argsForZygote中,方法的最后会调用zygoteSendArgsAndGetResult方法,需要注意的是,zygoteSendArgsAndGetResult方法的第一个参数中调用了openZygoteSocketIfNeeded方法,而第三个参数是保存应用进程的启动参数的argsForZygote。
zygoteSendArgsAndGetResult方法如下所示:
zygoteSendArgsAndGetResult 方法的主要作用就是将传入的应用进程的启动参数argsForZygote写入ZygoteState中,ZygoteState是ZygoteProcess的静态内部类,用于表示与Zygote进程通信的状态。
3.1.5 ZygoteProcess中对abi的处理
我们知道ZygoteState其实是由openZygoteSocketIfNeeded方法返回的,那么我们接着来看openZygoteSocketIfNeeded方法做了什么,代码如下所示:
在Android系统启动流程中,我们已经知道在Zygote的main方法中会创建name为“zygote”的Server端Socket。
而从以上代码可以看出:
- 在注释1处会调用ZygoteState的connect方法与名称为ZYGOTE_SOCKET的Socket建立连接,这里ZYGOTE_SOCKET的值为“zygote”,也就是说,在注释1处与Zygote进程建立Socket连接,并返回ZygoteState类型的primaryZygoteState对象。
- 在注释2处如果primaryZygoteState与启动应用程序进程所需的ABI不匹配,则会在注释3处连接name为“zygote_secondary”的Socket。
在Android系统启动流程中,已经曾经讲到过Zygote的启动脚本有4种,如果采用的是init.zygote32_64.rc或者init.zygote64_32.rc,则name为“zygote”的为主模式,name为“zygote_secondary”的为辅模式。
所以注释2和注释3处的意思简单来说就是,如果连接Zygote主模式返回的ZygoteState与启动应用程序进程所需的ABI不匹配,则连接Zygote辅模式。如果在注释4处连接Zygote辅模式返回的ZygoteState与启动应用程序进程所需的ABI也不匹配,则抛出ZygoteStartFailedEx异常。
这里也解释了为什么游戏Android系统无法运行甚至安装某些APP,因为它无法构建出应用程序所需要的abi类型。
3.1.6 ZygoteProcess的最终处理
从attemptZygoteSendArgsAndGetResult()方法可以看出,在与Zygote的Socket正常连接且无其它异常后,会在此将创建进程所需数据输出到Zygote的Socket端并等待进程创建的结果,最终将结果回调至上层。
3.2 Zygote接收请求并创建应用程序进程
Zygote接收请求并创建应用程序进程的时序图如图所示。
3.2.1 Zygote的初始化
Socket连接成功并匹配ABI后会返回ZygoteState类型对象,我们在分析zygoteSendArgsAndGetResult 方法中讲过,会将应用进程的启动参数argsForZygote写入ZygoteState中,这样Zygote进程就会收到一个创建新的应用程序进程的请求,我们回到ZygoteInit的main方法,如下所示:
从main的代码可以看出,Zygote初始化时:
- 通过registerZygoteSocket方法创建了一个Server端的Socket,这个name 为“zygote”的Socket用来等待AMS请求Zygote,以创建新的应用程序进程,关于AMS后面的章节会进行介绍。
- 预加载类和资源。
- 启动SystemServer进程,这样系统的服务也会由SystemServer进程启动起来。
- 调用ZygoteServer的runSelectLoop方法来等待AMS请求创建新的应用程序进程。
查看ZygoteServer的runSelectLoop方法:
从以上代码截图可以看出,Zygote初始化时会创建一个zygoteserver,在while()死循环中等待AMS申请创建进程的请求。
在收到请求后会调用ZygoteConnection的processOneComnd()方法来处理并生成一个Runable。
3.2.2 ZygoteConnection的processOneComnd()
先下结论,ZygoteConnection的processOneComnd()成功返回runnable后调用run方法,应用程序进程就创建完成了并且运行了主线程的管理类ActivityThread。
查看 ZygoteConnection的processOneComnd():
从以上代码截图可知:
- 在注释1处调用readArgumentList方法来获取应用程序进程的启动参数。
- 在注释2处将readArgumentList方法返回的字符串数组args封装到Arguments类型的parsedArgs对象中。
- 在注释3处调用Zygote的forkAndSpecialize方法来创建应用程序进程,参数为parsedArgs中存储的应用进程启动参数,返回值为pid。 forkAndSpecialize方法主要是通过fork当前进程来创建一个子进程的,如果pid等于0,则说明当前代码逻辑运行在新创建的子进程(应用程序进程)中,这时就会调用handleChildProc方法来处理应用程序进程,如下所示:
handleChildProc方法中调用了ZygoteInit的zygoteInit方法,如下所示:
zygoteInit方法中会在新创建的应用程序进程中创建Binder线程池,然后调用了RuntimeInit的applicationInit方法:
在applicationInit方法中会调用findStaticMinn()方法,需要注意的是,第一个参数args.startClass,它指的就是android.app.ActivityThread。
接着查看findStaticMinn()方法,如下所示:
从代码截图可以看到:
通过反射获得了android.app.ActivityThread类
通过反射获得了ActivityThread的main方法,并将main方法传入MethodAndArgsCaller类的构造方法中。
最后查看MethodAndArgsCaller类:
代码中的mMethod指的就是ActivityThread的main方法,调用了mMethod的invoke方法后,ActivityThread的main方法就会被动态调用,应用程序进程就进入了ActivityThread的main方法中。
通过代码也可以看到MethodAndArgsCaller实现了Runnable,那么run()方法在哪执行呢?
其实一路跟随源码已经发现它处于一个不断回调的过程:
通过代码截图可以看出它就是ZygoteConnection的proceseeOneCommand()方法的返回结果,也就是ZygoteInit在循环中收到了AMS的创建进程请求后会去执行一系列具体的创建进程工作,并在最后去构造这个runnable,最终成功构造则调用它的run方法,而run方法会去执行ActivityThread的main()方法,至此应用程序进程就创建完成了并且运行了主线程的管理类ActivityThread。
3.3 Binder线程池启动过程
很明显nativeZygoteInit是一个JNI方法,它对应的函数是什么呢? 对应源码地址:androidxref.com/9.0.0_r3/xr… 在AndroidRuntime.cpp的JNINativeMethod数组中我们得知它对应的函数是com_android_internal_os_ZygoteInit_nativeZygoteInit,如下所示:
接着来查看com_android_internal_os_ZygoteInit_nativeZygoteInit函数:
gCurRuntime是AndroidRuntime类型的指针,它是在AndroidRuntime初始化时就创建的,如下所示:
AppRuntime继承自AndroidRuntime,AppRuntime创建时就会调用AndroidRuntime的构造函数,gCurRuntime就会被初始化,它指向的是AppRuntime,我们来查看AppRuntime的onZygoteInit函数,AppRuntime在app_main.cpp中实现,如下所示:
最后一行会调用ProcessState的startThreadPool函数来启动Binder线程池:
支持Binder通信的进程中都有一个ProcessState类,它里面有一个mThreadPoolStarted变量,用来表示Binder线程池是否已经被启动过,默认值为false。在每次调用startThreadPool函数时都会在注释1处先检查这个标记,从而确保Binder线程池只会被启动一次。如果Binder 线程池未被启动,则在注释2处设置mThreadPoolStarted为true,并调用spawnPooledThread函数来创建线程池中的第一个线程,也就是线程池的主线程,如下所示:
可以看到Binder线程为一个PoolThread。在注释1处调用PoolThread的run函数来启动一个新的线程。下面来查看PoolThread类做了什么:
PoolThread类继承了Thread类。在注释1处调用IPCThreadState的joinThreadPool函数,将当前线程注册到Binder驱动程序中,这样我们创建的线程就加入了Binder线程池中,新创建的应用程序进程就支持Binder进程间通信了,我们只需要创建当前进程的Binder对象,并将它注册到ServiceManager中就可以实现Binder进程间通信,而不必关心进程间是如何通过Binder进行通信的。
3.4 消息循环创建过程
已知mMethod指的就是ActivityThread的main方法,mArgs指的是应用程序进程的启动参数。在注释1处调用ActivityThread的main方法,代码如下所示:
ActivityThread类是用于管理当前应用程序进程的主线程,
- 在注释1处创建主线程的消息循环Looper
- 在注释2处创建ActivityThread
- 在注释3处判断Handler类型的sMainThreadHandler 是否为null
- 如果为null则在注释4处,获取H类并赋值给sMainThreadHandler,这个H类继承自Handler,是ActivityThread的内部类,用于处理主线程的消息循环
- 在注释5处调用Looper的loop方法,使得Looper开始处理消息
可以看出,系统在应用程序进程启动完成后,就会创建一个消息循环,这样运行在应用程序进程中的应用程序可以方便地使用消息处理机制。