@Dlive

本文档:

使用的Android源码版本为:Android-4.4.3_r1 kitkat

(源码下载: http://source.android.com/source/index.html)

使用的源码阅读工具为Source Insight

源码结构:


0x00 Zygote介绍

Zygote是在设备开启的时候init启动的其中一个进程。在Android系统中,所有的应用程序进程,以及用来运行系统关键服务的System进程都是由Zygote进程负责创建的,因为其行为很想受精卵的分裂行为,故取名Zygote。
Zygote进程是通过复制自身的方式创建System进程和应用程序进程的。由于Zygote进程在启动时会在内部创建一个虚拟机实例,因此通过复制Zygote进程而得到的System进程和应用程序进程可以快速地在内部获得一个虚拟机实例拷贝。

0x01 Zygote的启动过程

1.1 从init到app_process

Zygote由init进程启动,init是Linux系统中用户空间的第一个进程,由于Android是基于Linux内核的。所以init也是Android系统中用户空间的第一个进程。内核启动之后,系统就通过启动一个用户级程序init的方法来完成引导。init是第一个进程,进程id为1。

init进程需要做很多重要的工作,它负责创建系统中几个关键进程,比如我们这里要说的Zygote。

Zygote启动脚本:system/core/rootdir/init.rc

第1行:从启动脚本中可以看出Zygote进程是以服务形式启动的,并且对应的应用程序为/system/bin/app_process,启动参数—start-system-server表示启动Zygote之后需要马上将System进程启动起来

第3行:Zygote进程在启动过程中,在内部创建一个名称为Zygote的Socket,这个Socket使用来执行进程间通信的,权限设置为666即 rw-rw-rw-

第4-7行:onrestart表示Zygote进程重启时需要执行的命令

从上面的信息我们可以知道Zygote进程要执行的程序是/system/bin/app_process,它的源代码在

framework/base/cmds/app_process/app_main.cpp文件中

接下来我们分析app_main.cpp中的代码

这个main函数的功能很简单,检查传入的命令行参数,之前我们看到init.rc中传入了两个选项—zygote, --start-system-server,之后调用AppRuntime的start方法。

1.2 AppRuntime分析

AppRuntime对应的源码同样在

frameworks/base/cmds/app_process/app_main.cpp中,它继承自AndroidRuntime。

AppRuntime重载了onStarted, onZygote和onExit函数,前面app_main中调用的start方法在AndroidRuntime定义。

所以下面主要分析AndroidRuntime的源码

AndroidRuntime类定义在framework/base/core/jni/AndroidRuntime.cpp中。

AndroidRuntime的start函数的主要作用是启动Android系统运行时库,它主要做了三件事情

一是调用函数startVm启动虚拟机

startVm函数就是调用JNI的虚拟机创建函数,创建函数时的一些参数是在startVm中确定的

设置JNI check选项:

设置虚拟机的heapsize,默认为16MB

还有一些其他的选项如code cache的大小

二是调用函数startReg注册JNI方法

注册一些JNI函数,因为之后在Java层很多函数是使用native方式实现的,所以要提前注册JNI函数。

调用register_jni_procs进行JNI函数注册

注册的函数:

三是调用了com.android.internal.os.ZygoteInit类的main函数。

在之前app_main.c中的main函数调用start函数时传递的参数为:com.android.internal.os.ZygoteInit,即className的值

获取到类的完整名称后,调用toSlashClassName将类名转换为JN规范的类名com/android/internal/os/ZygoteInit

之后通过JNI的findClass方法,获取jclass,之后获取类中main函数ID,然后通过CallStaticVoidMethod方法调用Java层静态方法。

自此进入Java层。

关于JNI的介绍可以参考我的博客上的《Android JNI总结》这篇文章:

http://www.cnblogs.com/dliv3/p/5423243.html

1.3 进入Java层

之前在AndroidRuntime的start方法中通过JNI调用了Java层ZygoteInit的main方法。

main方法主要做了三件事情

一是调用registerZygoteSocket函数创建了一个socket接口,用来和ActivityManagerService通讯

registerZygoteSocket创建一个服务端Socket

二是调用startSystemServer函数来启动SystemServer组件

startSystemServer会创建Java层中系统Service所驻留的进程system_server,该进程是framework的核心。

startSystemServer的关键代码如下,Zygote fork出一个system_server进程

三是调用函数进入一个无限循环在前面创建的socket接口上等待ActivityManagerService请求创建新的应用程序进程。

runSelectLoop关键代码如下:

runSelectLoop处理客户端和客户请求,客户在zygote中用ZygoteConnection对象来表示,客户请求由ZygoteConnection的runOnce来处理。


1.4 Zygote启动过程总结

用一个时序图来简要展现Zygote启动过程


0x02 Zygote的分裂

之前Zygote通过runSelectLoop等待并处理来自客户的消息,以一个Activity的启动为例,具体分析Zygote的分裂过程。

2.1 客户端请求

ActivityManagerService由SystemServer创建。

ActivityManagerService源码位置

frameworks\base\services\java\com\android\server\am\ActivityManagerService.java

ActivityManagerService的startProcessLocked函数源码如下:

调用了Process.start函数:

接着在Process.start中调用了startViaZygote

startViaZygote中调用了zygoteSendArgsAndGetResult函数

接着又调用了openZygoteSocketIfNeed,跟到openZygoteSocketIfNeed函数实现可以看到函数中打开了Socket并进行读写操作,即ActivityManagerService向Zygote发生请求。请求参数中有一个字符串值为“android.app.ActivityThread”


2.2 Zygote响应请求

在之前分析Zygote的启动过程时,Zygote最后调用了runSelectLoop,runSelectLoop中处理客户端请求。

处理过程如下:

当有请求数据发来时,Zygote就会调用ZygoteConnection的runOnce函数。

ZygoteConnection.runOnce函数关键代码如下:

可以看到Zygote又分裂出一个子进程,子进程会调用handleChildProc函数如下所示(同样在ZygoteConnection.runOnce函数代码中)


2.3 Zygote分裂过程总结

和启动过程一样,也用一个时序图来简要展现Zygote的分裂过程


0x03 参考资料

1. 《深入理解Android 卷1》 邓凡平

2. 《Android系统源代码情景分析》 罗升阳

3. 《Android源码分析实录》 李忠良

4. Android系统进程Zygote启动过程的源码分析

http://blog.csdn.net/luoshengyang/article/details/6768304

5. Zygote进程 – Zygote的分裂

http://blog.csdn.net/zhgxhuaa/article/details/24584807

6. Android JNI总结

http://www.cnblogs.com/dliv3/p/5423243.html

Android源码阅读 – Zygote的更多相关文章

  1. Android拓展系列(11)--打造Windows下便携的Android源码阅读环境

    因为EXT和NTFS格式的差异,我一直对于windows下阅读Android源码感到不满. 前几天,想把最新的android5.0的源码下下来研究一下,而平时日常使用的又是windows环境,于是专门 ...

  2. Android源码阅读技巧--查找开发者选项中显示触摸操作源码

    在开发者模式下,在开发者选项中,可以勾选“显示触摸操作”,然后只要点击屏幕就会在点击的位置有圈圈显示.如何找到绘制圈圈的代码部分,有什么技巧来阅读代码量这么大的android系统源码呢?以下请跟着小老 ...

  3. Android源码阅读-Filter过滤器

    Filter 顺便看看,Android中过滤器是怎么实现的? 注释中提到,Filter一般通过继承Filterable实现 具体实现 这是SimpleAdapter出现的一个过滤首字母item的一个过 ...

  4. Android 源码阅读笔记

    Zygote: .Zygote 是系统启动之后创建的第二个进程2.Zygote 创建zygote Socket.虚拟机3.Zygote 在虚拟机中通过forkSystemServer, 创建Serve ...

  5. Android 源码阅读之SMS,MMS

    主界面: com.android.mms.ui.ConversationList.java  [extends ListActivity] 点击新建信息:onListItemClick -〉 posi ...

  6. Android源码阅读笔记二 消息处理机制

    消息处理机制: .MessageQueue: 用来描述消息队列2.Looper:用来创建消息队列3.Handler:用来发送消息队列 初始化: .通过Looper.prepare()创建一个Loope ...

  7. 【安卓本卓】Android系统源码篇之(一)源码获取、源码目录结构及源码阅读工具简介

    前言        古人常说,“熟读唐诗三百首,不会作诗也会吟”,说明了大量阅读诗歌名篇对学习作诗有非常大的帮助.做开发也一样,Android源码是全世界最优秀的Android工程师编写的代码,也是A ...

  8. Android拓展系列(10)--使用Android Studio阅读整个Android源码

    之前一直在windows下用source insight阅读android源码,效果非常好.后来远程异地服务器,网络限制,一直用ssh + vim,现在主要还是以这种方式.最近发现一个不错的东西(早就 ...

  9. 【Android 系统开发】使用 Source InSight 阅读 Android 源码

    1. 安装 Source Insight (1) Source Insight 相关资源 安装相关资源 : -- 下载地址 : http://www.sourceinsight.com/down35. ...

随机推荐

  1. 由于服务器意外的断电,导致SQL SERVER服务器上数据库出现“置疑”而无法使用,

    来自百度 1.停止数据库服务器,将数据库MDF文件和LDF文件复制备份一份2.启动数据库服务器,删除置疑的数据库3.仅用备份的数据库MDF文件附加数据库,sp_attach_db或者sp_attach ...

  2. maven打包jar包

    参考http://www.cnblogs.com/justinzhang/p/4983633.html 新建jar类型的maven project (选择simple project ) 配置 < ...

  3. Think twice before doing~

    1.遇到任何矛盾,对事不对人. 2.接到朋友等人的求助电话后,一定要先问清楚对方有什么事情,然后再告诉他(她)能不能帮她(他). 3.如果没有十足的把握和必要,就不要轻易说假话. 4.少提自己的私事, ...

  4. css权威指南学习笔记

    2016-08-03 1,继承 一般大多数框模型属性都是不能继承的.如:padding .margin .border .background 都不能继承. 继承值,完全没有特殊性.(就是优先级最低) ...

  5. 初学Vue2.0--基础篇

    概述: 鉴于本人初学,使用的编译器是webStorm,需添加对VUE的支持,添加方法可以参考 http://www.jianshu.com/p/142dae4f8b51. 起步: 1. 扎实的 Jav ...

  6. Java网络编程--简单聊天程序

    背景 毕业设计前的练手,学校小比赛中的一个题目. 开发环境 Java(eclipse)+Mysql 简介 使用Java+Mysql开发以个简单的聊天工具,在本次项目中实现了: 1. 用户登录(客户端至 ...

  7. TeXstudio 编写Latex论文的若干问题

    TeXstudio 编写Latex论文的若干问题解决方案总结       问题1: 如何安装TeXstudio 以及 Texstudio当中的中文字体使用问题.   一.如何安装TeXstudio 很 ...

  8. SpringMVC学习记录1

    起因 以前大三暑假实习的时候看到公司用SpringMVC而不是Struts2,老司机告诉我SpringMVC各种方便,各种解耦. 然后我自己试了试..好像是蛮方便的.... 基本上在Spring的基础 ...

  9. C语言基础(11)-随机数发生器

    一. rand() rand是一个C语言库函数,功能是生成一个随机数.rand需要一个不同的种子,才能生成不同的随机数. 二. srand(int seed) rand需要一个不同的种子,才能生成不同 ...

  10. Oracle的表锁死以及解锁

    Oracle的表锁死以及解锁 oracle 查看锁死的表,锁死的进程. select sess.sid, sess.serial#, lo.oracle_username, lo.os_user_na ...