前言
Android研习社第二期技术分享的录播视频,已经放到B站上了,大家可以戳链接www.bilibili.com/video/av712…食用
这篇文章,一来是Android研习社
第二期技术分享的视频讲义,二来也对上一篇的Zygote源码分析进行了一个补充,水平有限,还请大家多多指教
源码阅读工具
understand 5.1
源码阅读方法
-
如何把源码读起来
阅读相关技术文章,总结重要的知识点,给自己提问题,去源码中找答案,有一个针对性
-
如何抓大放小
源码很庞大,涉及的细节和深度也比较多,要清楚自己当前,想搞懂的是什么问题
-
如何把握主要问题
没有定论,多阅读多体会,阅读相关技术文章和读源码穿插结合
源码领读:Zygote源码分析
主要问题分析:Zygote进程主要流程分析
本来的想法是分析Zygote进程是如何被启动起来的,后来发现没啥东西,所以今天还是分析下Zyogte主要做了些什么事情;目的呢,其实还是让大家知道如何去读源码,正所谓授人以渔,不如授人以渔
请戳链接食用:www.bilibili.com/video/av712…
再谈Zygote,由厚到薄
Zygote进程的启动都经历了哪些流程
我们先来大概梳理下Zygote进程的启动都经历了哪些流程

深入分析
为什么要使用脚本
我们来考虑下,这里为什么要使用脚本,同时又要搞一套脚本解析的逻辑,来对zygote进行初始化呢?如果写死到逻辑里,是否可以呢?这里我们先留一个问号,先接着往下分析
通过对脚本的解析,我们执行app_process的二进制文件开启一个进程,并把这个进程名改为zygote,然后对该进程进行初始化操作,这里我们还需要进一步分析,初始化过程中,究竟做了什么事情;
最后,进入一个死循环,用socket通信来接收子进程发送过来的消息,这里的socket是服务端,其他进程相当于客户端,所以代码中命名为ZygoteServer,就是这个意思
在这个死循环中,使用了多路IO复用的机制(select机制),这个也需要去进一步分析
进入死循环后,相当于当前进程一直处于运行状态,那么我们也要接着去执行下面的逻辑呀,不能卡死在这里呀,所以我们又fork出一个重要进程,SystemServer,由这个进程去开启一系列的系统服务,比如AMS,PMS,WMS,这些系统服务都是跑在一个进程下的(这个需要进一步确认),由这些系统服务提供一些公共的东西给其他进程来调度和使用
为什么这么设计
这么设计的原因,我们来简单的猜测下。如果没有这些系统服务,那我们如何去调度系统资源呢?每个进程都需要主动找系统层去要,那么系统层就要把这些逻辑,比如跨进程的消息处理,多线程的安全问题,都要写在复杂的逻辑中去。如果把这些逻辑抽离出来,一来,相当于收拢了相关功能的处理权限;二来,各个服务职责单一,也简化了代码,提升了代码的可阅读性和可维护性
另外,为什么要单开一个进程来维护这些系统服务呢?就算我调用了runSelectLoop()进入了死循环,那其实还可以另开一个线程啊!
我觉得这个就是跟整体的设计相关了,比如说,咱们做一个项目,其中有一个模块是相对独立的,跟其他业务是没有什么关系的,比如音视频播放,或者Webview展示H5页面,类似的功能,那我们其实一般是会单独开启一个子进程的。我觉得系统层面的设计也有类似的考虑,如果zygote进程出了问题,那就重新初始化zygote就行了,如果在init进程出了问题,就针对init做单独的业务处理,保证他们互相的独立性,和业务上的解耦,互相都不会影响;如果是开启一个线程,就可能需要处理各种各样的问题
SystemServer
,可以说是Java世界的头号进程--Zygote
--诞生一来,fork出来的第一个子进程,这个fork出的进程,内部是如何设计的,如何维护这个系统服务的,这个也是我们接下来的SystemServer
源码要分析的部分
我们再来探讨下,Zygote
为什么要设计一个跟子进程通信的ZygoteServer
,上面我们也提到了,它内部是维护了两个Socket对象,zygoteSocket
和uaspSocket
,那么我们就要了解,Linux中,经典跨进程通信的方案有哪些了。Socket是进程间通信的一种方式,而且,是可以无视Native世界和Java世界的。也可以说,它是一种协定好的通信方案。像我们之前做的游戏辅助应用,我们需要通过adb来开启一个native进程,这个进程又是需要跟App所在的进程进行通信的,那么,在这种场景下,我们就是使用了Socket通信的方式,一个作为server端,一个作为client端,进行数据的传递。
Zygote进程,是由init进程通过执行exec
(需要确认)的系统调用开启的,它是沟通Java世界和native世界的桥梁,zygote进程最终是在Java世界中的,这里我们的zygote跟它的子进程通信,也需要一个一对多的数据通信设计(一个Zyogte会fork出多个子进程)。
为什么要有一个母体
我这里还想谈一谈,为什么要设计有一个母体,fork出子进程这种进程的运行方式。有一些资源是可以共享的,比如VM的运行环境,那么我想再开启一个子进程,又想同时对VM的运行环境进行复用,这么来看,fork出一个子进程,是一个比较好的方式;同时,32位的zygote和64位的zygote需要在不同的VM环境下运行,所以才会有两个zygote--primeryZygote
和secondZygote
那么什么又是VM呢?简单来讲,就是运行环境,这个运行环境不是硬件层的,而是软件层面的,比如像我们开发App,也需要又SDK,NDK之类的工具包,才能进行开发。VM也是同理,提供一些共有的环境,供进程来使用,比如各自的私有目录,进程及进程组的权限,等等
接下来要做的事
- SystemServer源码分析(下周)
- 系统启动流程整体分析(下下周?)
- 10分钟搞定源码,系列短视频(下下下周?)
- 源码动态调试(待定)
写在最后
原创不易,坚持更难。 如果你想继续看到我接下来的分享,请通过点赞的方式告诉我,你的鼓励是我继续创作的最大动力!
郑重声明
本文由Android研习社社群创作,版权©️归Android研习社
所有,侵权必究!