Android10.0应用进程创建过程以及Zygote的fork流程


Android10.0应用进程创建过程以及Zygote的fork流程

阅读本文大约需要花费1小时。

文章的内容主要还是从源码进行分析,虽然又臭又长,但是如果想要学习Android系统源码,这是必要走的路,没有捷径。

相对于碎片学习,我更倾向于静下心来花费1个小时认真的学习一段内容。

专注于Android系统级源码分析,Android的平台设计,欢迎关注我,谢谢!

上一节我们讲完了Launcher的启动流程,这一节来看看应用进程的创建过程以及Zygote的fork流程。

系列文章:

1.概述

上一节我们学习了Launcher的启动流程。这一节来介绍下应用进程的创建过程以及Zygote Fork的过程。

点击桌面图标启动应用概述:

在上一节Launcher的启动中我们知道了,手机的桌面其实就是Launcher进程,里面的应用图标都是Launcher通过ListView进行展示。

那么我们点击一个桌面图标,比如微信,这个应用是如何启动的呢,这一节我们从系统级的源码来一步步的进行分析。

在分析之前,我们简单区分一下进程和线程的概念。

在Android中通过Logcat抓取log时,存在PID和TID两个概念。

PID:Process ID,进程ID

TID: Thread ID,线程ID

每个Android都是一个进程,每个进程有一个或多个线程

进程:

是并发执行的程序在执行过程中分配和管理资源的基本单位,是一个动态概念,竞争计算机系统资源的基本单位。

当我们点击某个应用的图标时,必须创建一个进程,该进程是由Zygote fork出来的,进程具有独立的资源空间,用于承载App上运行的各种Activity/Service等组件。


线程:

是进程的一个执行单元,是进程内科调度实体。比进程更小的独立运行的基本单位。线程也被称为轻量级进程。

每个应用有多个线程,例如UI展示属于UI主线程,一些通信过程属于独立线程,通常JAVA中使用new Thread().start()来创建一个新的线程。

该线程并没有自己独立的地址空间,而是与其所在进程之间资源共享。


进程线程的区别

  1. 地址空间:同一进程的线程共享本进程的地址空间,而进程之间则是独立的地址空间。
  2. 资源拥有:同一进程内的线程共享本进程的资源,但是进程之间的资源是独立的。
  3. 一个进程崩溃后,在保护模式下不会对其他进程产生影响,但是一个线程崩溃整个进程都死掉。所以多进程要比多线程健壮。
  4. 进程切换时,消耗的资源大,效率高。所以涉及到频繁的切换时,使用线程要好于进程。同样如果要求同时进行并且又要共享某些变量的并发操作,只能用线程不能用进程。
  5. 执行过程:每个独立的进程有一个程序运行的入口、顺序执行序列和程序入口。但是线程不能独立执行,必须依存在应用程序中,由应用程序提供多个线程执行控制。
  6. 线程是处理器调度的基本单位,但是进程不是。
  7. 两者均可并发执行。

2.核心源码


Android10.0应用进程创建过程以及Zygote的fork流程

3.架构

App发起进程:点击一个桌面应用(例如微信),Launcher 加载应用, LauncherActivity收到触发事件,组装Intent,通过binder发送消息给SystemServer进程,调用Activity的startActivity()来启动进程,启动Activity时,受ActivityManagerService-AMS的服务控制,AMS属于SystemServer进程,因此SystemServer进行会通过Process 来向Zygote发送一个Socket。

Zygote有一个无限循环,一直在等待Socket请求,收到SystemServer发来新的Socket请求后,Zygote调用系统的fork函数来孵化一个新的进程,比如这里的微信。

再把启动的入口交给ActivityThread,进入微信的进程中,进行详细的UI展示。


3.1 进程创建图

从点击Launcher中的图标,到启动Activity,再到Zygote Fork操作,最终进入新的进行进行UI绘制。


Android10.0应用进程创建过程以及Zygote的fork流程

3.2 Zygote Fork图

Zygote调用系统的fork()函数,孵化出一个新的进程,fork()采用copy-on-write机制,有些类如果不做改变,甚至都不用复制,子进程可以和父进程共享这部分数据,从而省去不少内存的占用。

图片来源Gityuan


Android10.0应用进程创建过程以及Zygote的fork流程

4.源码分析

应用的启动共分以下四个步骤完成:

  1. 点击桌面的图标,Launcher调用系统的startActivity进行启动Activity,此时的动作在Launcher进程中
  2. ATM\\AMS 进行Activity的处理,组装message,通过socket发送给Socket
  3. Zygote收到SystemServer发来的消息,进行消息拆分,再调用系统的fork()函数,进行进行孵化操作。
  4. 进入ActivityThread的main(),完成最终应用进程的的onCreate操作

接下来我们根据这四个步骤来进行详细的源码分析.


4.1 第一阶段,点击桌面图标,触发点击事件

触发Launcher listview的点击事件 onListItemClick()

说明:桌面图标按照5*5或者6*6的方式进行排列,这其实是Launcher进程展示的ListView,每个应用图标填入其中,点击图标进入Launcher的点击事件处理

源码:

Android10.0应用进程创建过程以及Zygote的fork流程

4.1.1 [Activity.java]

startActivity()

说明:这里比较简单,调用

startActivityForResult()

源码:

Android10.0应用进程创建过程以及Zygote的fork流程

4.1.2 [Activity.java]

startActivityForResult()

说明:不难发现,不论有没有父Activity,最终都交给了 Instrumentation 来开启

源码:

Android10.0应用进程创建过程以及Zygote的fork流程

4.1.3 [Instrumentation.java]

execStartActivity()

说明:Binder 调用 ActivityTaskManagerService-ATM 来启动 Activity

源码:


Android10.0应用进程创建过程以及Zygote的fork流程

从下面代码可以看到,IActivityTaskManager其实获得的是activity_task对应服务的Binder对象,

即是ActivityTaskManagerService-ATM

Android10.0应用进程创建过程以及Zygote的fork流程

4.2 第二阶段:ATM\\AMS 进行Activity的处理

调用栈如下:

Android10.0应用进程创建过程以及Zygote的fork流程

4.2.1 [ActivityTaskManagerService.java]

startActivity()

说明:

这里很简单,直接调用startActivityAsUser()

源码:

Android10.0应用进程创建过程以及Zygote的fork流程

4.2.2 [ActivityTaskManagerService.java]

startActivityAsUser()

说明:获取 ActivityStarter 对象,最终调用ActivityStarter的execute()

源码:

Android10.0应用进程创建过程以及Zygote的fork流程

4.2.3 [ActivityStarter.java] execute()

说明:根据[4.2.2]中调用了setMayWait,因此这里的mRequest.mayWait为true

源码

Android10.0应用进程创建过程以及Zygote的fork流程

4.2.4 [ActivityStarter.java]

startActivityMayWait()

说明:调用startActivity()来启动Activity

源码:

Android10.0应用进程创建过程以及Zygote的fork流程

4.2.5 [ActivityStarter.java]

startActivity()

说明:延时布局,然后通过startActivityUnchecked()来处理启动标记 flag ,要启动的

Android10.0应用进程创建过程以及Zygote的fork流程

4.2.6 [RootActivityContainer.java]

resumeFocusedStacksTopActivities()

说明:获取栈顶的Activity,恢复它

源码:

Android10.0应用进程创建过程以及Zygote的fork流程

4.2.7 [ActivityStackSupervisor.java]

startSpecificActivityLocked()

说明:

发布消息以启动进程,以避免在ATM锁保持的情况下调用AMS时可能出现死锁,最终调用到ATM的startProcess()

源码:

Android10.0应用进程创建过程以及Zygote的fork流程

4.2.8 [ActivityManagerService.java]

startProcess()

说明:

一路调用Process start(),最终到ZygoteProcess的

attemptUsapSendArgsAndGetResult(),用来fork一个新的Launcher的进程

源码:

Android10.0应用进程创建过程以及Zygote的fork流程

调用栈如下:

Android10.0应用进程创建过程以及Zygote的fork流程

4.2.9 [ZygoteProcess.java]

attemptZygoteSendArgsAndGetResult()

说明:通过Socket连接Zygote进程,把之前组装的msg发给Zygote,其中processClass ="android.app.ActivityThread",通过Zygote进程来Fork出一个新的进程,

并执行 "android.app.ActivityThread"的main方法

源码:

Android10.0应用进程创建过程以及Zygote的fork流程

4.3 第三阶段 Zygote Fork 应用进程

说明:Zygote的启动过程我们前面有详细讲到过。

SystemServer的AMS服务向启动Home Activity发起一个fork请求,Zygote进程通过Linux的fork函数,孵化出一个新的进程。

由于Zygote进程在启动时会创建Java虚拟机,因此通过fork而创建的Launcher程序进程可以在内部获取一个Java虚拟机的实例拷贝。

fork采用copy-on-write机制,有些类如果不做改变,甚至都不用复制,子进程可以和父进程共享这部分数据,从而省去不少内存的占用。

调用栈如下:

Android10.0应用进程创建过程以及Zygote的fork流程

4.3.1 [ZygoteInit.java] main()

说明:Zygote先fork出SystemServer进程,接着进入循环等待,用来接收Socket发来的消息,用来fork出其他应用进程,比如Launcher

源码:

Android10.0应用进程创建过程以及Zygote的fork流程

4.3.2 [ZygoteConnection.java]

processOneCommand()

说明:通过 forkAndSpecialize()来fork出Launcher的子进程,并执行handleChildProc,进入子进程的处理

源码:

Android10.0应用进程创建过程以及Zygote的fork流程

4.3.3 [Zygote.java] forkAndSpecialize

说明:主要是调用dalvik中ZygoteHooks的preFrok进行预处理,再调用postForkCommon进行完成的进程fork

源码:

Android10.0应用进程创建过程以及Zygote的fork流程

4.3.3.1 [ZygoteHooks.java] preFork()

说明:Zygote进程有4个Daemon子线程分别是

HeapTaskDaemon、

ReferenceQueueDaemon、

FinalizerDaemon、

FinalizerWatchdogDaemon

preFork()预处理主要是先停止4个子线程,等待所有的子线程结束,最后完成gc堆的初始化工作

Zygote子线程如下图所示:

Android10.0应用进程创建过程以及Zygote的fork流程

源码:

Android10.0应用进程创建过程以及Zygote的fork流程

4.3.3.2 [Daemons.java] stop()

说明:此处守护线程Stop方式是先调用目标线程interrrupt()方法,然后再调用目标线程join()方法,等待线程执行完成

停止4个子线程,分别是:Java堆整理线程;引用队列线程;析构线程;析构监控线程

源码:

Android10.0应用进程创建过程以及Zygote的fork流程

4.3.3.3 [ZygoteHooks.java]

waitUntilAllThreadsStopped()

说明:等待所有子线程结束

源码:

Android10.0应用进程创建过程以及Zygote的fork流程

4.3.4 [ZygoteHooks.java]

nativePreFork()

通过JNI最终调用的是以下方法:

[dalvik_system_ZygoteHooks.cc] ZygoteHooks_nativePreFork()

说明:进行堆的一些预处理

源码:

Android10.0应用进程创建过程以及Zygote的fork流程

4.3.4.1 [runtime.cpp] PreZygoteFork()

说明:堆的初始化工作,属于虚拟机的范畴,想理解的可以深挖一下

源码:

Android10.0应用进程创建过程以及Zygote的fork流程

4.3.5 [Zygote.java]

nativeForkAndSpecialize()

通过JNI最终调用的是以下方法:

[com_android_internal_os_Zygote.cpp] com_android_internal_os_Zygote_nativeForkAndSpecialize

说明: fork 子进程

源码:

Android10.0应用进程创建过程以及Zygote的fork流程

4.3.5.1 [com_android_internal_os_Zygote.cpp]

ForkCommon()

说明:调用系统的fork()进行 应用进程的孵化操作,采用copy-on-write的机制,使得应用进程与Zygote共享部分数据,减少内存的占用

源码:

Android10.0应用进程创建过程以及Zygote的fork流程

4.3.5.2 [com_android_internal_os_Zygote.cpp]

SpecializeCommon()

说明:进行进程的一些资源处理,selinux权限处理,并调用Zygote的callPostForkChildHooks()

源码:

Android10.0应用进程创建过程以及Zygote的fork流程

4.3.5.3 [Zygote.java]

callPostForkChildHooks()

说明:JAVA堆线程的一些处理

源码:

Android10.0应用进程创建过程以及Zygote的fork流程

创建JAVA的线程池,设置信号处理,启动JDWP线程

Android10.0应用进程创建过程以及Zygote的fork流程

4.3.6 [ZygoteHooks.java] postForkCommon()

说明:在fork新进程后,启动Zygote的4个Daemon线程,java堆整理,引用队列,以及析构线程。

源码:

Android10.0应用进程创建过程以及Zygote的fork流程

启动Zygote的4个新的子线程

Android10.0应用进程创建过程以及Zygote的fork流程

4.3.7 [ZygoteConnection.java]

handleChildProc()

说明:进行子进程的操作,最终获得需要执行的ActivityThread的main()

源码:

Android10.0应用进程创建过程以及Zygote的fork流程

zygoteInit 进行一些环境的初始化、启动Binder进程等操作

Android10.0应用进程创建过程以及Zygote的fork流程

把之前传来的"android.app.ActivityThread" 传递给findStaticMain

Android10.0应用进程创建过程以及Zygote的fork流程

通过反射,拿到ActivityThread的main()方法

Android10.0应用进程创建过程以及Zygote的fork流程

把反射得来的ActivityThread main()入口返回给ZygoteInit的main,通过caller.run()进行调用

Android10.0应用进程创建过程以及Zygote的fork流程

至此,Zygote fork进程的操作全部完成,下一步进入JAVA世界,进行真正的Activity的启动流程。


4.4 第四阶段 进入应用进程,启动Activity的onCreate()

调用栈如下:

Android10.0应用进程创建过程以及Zygote的fork流程

4.4.1 [ActivityThread.java] main()

说明: 主线程处理, 创建ActivityThread对象,调用attach进行处理,最终进入Looper循环

源码:

Android10.0应用进程创建过程以及Zygote的fork流程

调用ActivityThread的attach进行处理

Android10.0应用进程创建过程以及Zygote的fork流程

4.4.2 [ActivityManagerService.java]
attachApplication()

说明:清除一些无用的记录,最终调用ActivityStackSupervisor.java的 realStartActivityLocked(),进行Activity的启动

源码:

Android10.0应用进程创建过程以及Zygote的fork流程

4.4.3 [ActivityStackSupervisor.java]

realStartActivityLocked()

说明:真正准备去启动Activity,通过clientTransaction.addCallback把LaunchActivityItem的obtain作为回调参数加进去,再调用

ClientLifecycleManager.scheduleTransaction()得到LaunchActivityItem的execute()方法进行最终的执行

参考上面的第四阶段的调用栈流程:

Android10.0应用进程创建过程以及Zygote的fork流程

源码:

Android10.0应用进程创建过程以及Zygote的fork流程

4.4.4 [TransactionExecutor.java] execute()

说明:执行之前realStartActivityLocked()中的

clientTransaction.addCallback

调用栈:

Android10.0应用进程创建过程以及Zygote的fork流程

源码:

Android10.0应用进程创建过程以及Zygote的fork流程

4.4.5 [ActivityThread.java]

handleLaunchActivity()

说明:主要干了两件事,第一件:初始化WindowManagerGlobal;第二件:调用performLaunchActivity方法

源码:

Android10.0应用进程创建过程以及Zygote的fork流程

4.4.6 [ActivityThread.java]

performLaunchActivity()

说明:获取ComponentName、Context,反射创建Activity,设置Activity的一些内容,比如主题等;

最终调用callActivityOnCreate()来执行Activity的onCreate()方法

源码:

Android10.0应用进程创建过程以及Zygote的fork流程

callActivityOnCreate先执行activity onCreate的预处理,再去调用Activity的onCreate,最终完成Create创建后的内容处理

Android10.0应用进程创建过程以及Zygote的fork流程

performCreate()主要调用Activity的onCreate()

Android10.0应用进程创建过程以及Zygote的fork流程

至此,看到了我们最熟悉的Activity的onCreate(),应用启动的启动完成,应用程序被真正的调用起来。


5.总结

通过上面一系列的流程,我们理解了应用进程的创建流程,以及Zygote fork这些应用进程的流程。

主要分为4步完成

  1. 点击桌面的图标,Launcher调用系统的startActivity进行启动Activity,此时的动作在Launcher进程中
  2. 通过Binder向SystemServer进行发送消息,让ATM\\AMS 进行Activity的处理,组装message,通过socket发送给Socket,此时动作在SystemServer进程中
  3. Zygote收到SystemServer发来的消息,进行消息拆分,再调用系统的fork()函数,进行进行孵化操作,此时动作在Zygote进程中
  4. 进入ActivityThread的main(),完成最终应用进程的的onCreate操作,该步动作处于新创建的应用进程中



分享到:


相關文章: