由于源码分析的代码量比较大,大部分博客网站的内容显示页面都比较窄,显示出来的效果都异常丑陋,所以您也可以直接查看 《 Thinking in Android 》 来阅读这边文章(也可以点击 RSS 订阅查看代码更方便),希望这篇文章能帮你梳理清楚 “Zygote 进程的原理”。
关键类 | 路径 |
---|---|
init.rc | system/core/rootdir/init.rc |
init.cpp | system/core/init/init.cpp |
init.zygote64.rc | system/core/rootdir/init.zygote64.rc |
builtins.cpp | system/core/init/builtins.cpp |
service.cpp | system/core/init/service.cpp |
app_main.cpp | frameworks/base/cmds/app_process/app_main.cpp |
AndroidRuntime.cpp | frameworks/base/core/jni/AndroidRuntime.cpp |
JniInvocation.cpp | libnativehelper/JniInvocation.cpp |
LocalServerSocket.cpp | frameworks/base/core/java/android/net/LocalServerSocket.java |
ZygoteInit.java | frameworks/base/core/java/com/android/internal/os/ZygoteInit.java |
ZygoteServer.java | frameworks/base/core/java/com/android/internal/os/ZygoteServer.java |
在 Android 系统中,JavaVM(Java 虚拟机)
、应用程序进程
以及运行系统关键服务的 SystemServer 进程
都是由 Zygote
来创建的,我们也将它称为 孵化器
。它通过 fock
(复制进程)的形式来创建 "应用程序进程"
和 "SystemServer 进程"
,由于 Zygote 进程在启动时会创建 JavaVM,因此通过 fock 而创建的 “应用程序进程” 和 “SystemServer 进程” 可以在内部获取一个 JavaVM 的实例拷贝
。
在前面分析 init 进程 时,我们知道 init 进程启动后,会解析 init.rc 文件,然后创建和加载 "service"
字段指定的进程。zygote 进程就是以这种方式被 init 进程加载的。
在 system/core/rootdir/init.rc
中,可以看到:
// system/core/rootdir/init.rc
import /init.environ.rc
import /init.usb.rc
import /init.${ro.hardware}.rc
import /vendor/etc/init/hw/init.${ro.hardware}.rc
import /init.usb.configfs.rc
import /init.${ro.zygote}.rc // ${ro.zygote} 由厂商定义,与平台相关
在不同的平台(32、64 及 64_32)上,init.rc 将包含不同的 zygote.rc 文件。
在 system/core/rootdir
目录下:
有 init.zygote32_64.rc
、init.zyote64.rc
、init.zyote32.rc
、init.zygote64_32.rc
四个文件。
init.zygote32.rc
zygote 进程对应的执行程序是 app_process
(纯 32bit 模式)
init.zygote64.rc
zygote 进程对应的执行程序是 app_process64
(纯 64bit 模式)
init.zygote32_64.rc
启动两个 zygote 进程 (zygote 和 zygote_secondary),对应的执行程序分别是 app_process32
(主模式)、app_process64
init.zygote64_32.rc
启动两个 zygote 进程 (zygote 和 zygote_secondary),对应的执行程序分别是 app_process64
(主模式)、app_process32
那么,为什么要定义这么多种情况?
这主要是因为 Android 5.0 以后开始支持 64 位程序,为了兼容 32 位和 64 位才这样定义。不同的 zygote.rc 内容大致相同,主要区别体现在启动的是 32 位,还是 64 位的进程。init.zygote32_64.rc
和 init.zygote64_32.rc
会启动两个进程,且存在主次之分。
这里拿 64 位处理器为例,init.zygote64_32.rc 的代码如下所示:
/*
* 进程名称是 zygote
* 运行的二进制文件在 /system/bin/app_process64
* 启动参数是 -Xzygote /system/bin --zygote --start-system-server --socket-name=zygote
*/
service zygote /system/bin/app_process64
-Xzygote /system/bin --zygote --start-system-server --socket-name=zygote
class main
priority -20
user root
group root readproc reserved_disk
socket zygote stream 660 root system // 创建一个 socket,名字叫 zygote
socket usap_pool_primary stream 660 root system
onrestart write /sys/android_power/request_state wake // onrestart 指当进程重启时执行后面的命令
onrestart write /sys/power/state on
onrestart restart audioserver
onrestart restart cameraserver
onrestart restart media
onrestart restart netd
onrestart restart wificond
writepid /dev/cpuset/foreground/tasks // 创建子进程时,向 /dev/cpuset/foreground/tasks 写入 pid
// 另一个 service:zygote_secondary
service zygote_secondary /system/bin/app_process32
-Xzygote /system/bin --zygote --socket-name=zygote_secondary --enable-lazy-preload
class main
priority -20
user root
group root readproc reserved_disk
socket zygote_secondary stream 660 root system
socket usap_pool_secondary stream 660 root system
onrestart restart zygote
writepid /dev/cpuset/foreground/tasks
既然定义了此 service
用于启动 Zygote
,那么是在什么地方启动的呢?在探讨 init 的时候,我们分析过:init 进程启动的最后,会处理 late-init
事件。
// system/core/init/init.cpp
int SecondStageMain(int argc, char** argv) {
// Don't mount filesystems or start core system services in charger mode.
std::string bootmode = GetProperty("ro.bootmode", "");
if (bootmode == "charger") {
am.QueueEventTrigger("charger");
} else {
am.QueueEventTrigger("late-init");
}
return 0;
}
对应于 init.rc 配置文件中,我们找到如下代码:
// system/core/rootdir/init.rc
# Mount filesystems and start core system services.
on late-init
... ...
# Now we can start zygote for devices with file based encryption
trigger zygote-start // 触发了 zygote-start 事件后,就会启动 zygote 进程
... ...
# It is recommended to put unnecessary data/ initialization from post-fs-data
# to start-zygote in device's init.rc to unblock zygote start.
on zygote-start && property:ro.crypto.state=unencrypted
# A/B update verifier that marks a successful boot.
exec_start update_verifier_nonencrypted
start netd // start 对应的映射关系定义于 /system/core/init/builtins.cpp 中
start zygote // 调用 start 对应的处理函数,启动名为 zygote 的服务(传入前文 init.zygote.rc 中定义的参数)
start zygote_secondary
on zygote-start && property:ro.crypto.state=unsupported
# A/B update verifier that marks a successful boot.
exec_start update_verifier_nonencrypted
start netd
start zygote
start zygote_secondary
on zygote-start && property:ro.crypto.state=encrypted && property:ro.crypto.type=file
# A/B update verifier that marks a successful boot.
exec_start update_verifier_nonencrypted
start netd
start zygote
start zygote_secondary
start
命令有一个对应的执行函数 do_start()
,定义在 /system/core/init/builtins.cpp
中。
// system/core/init/builtins.cpp
// Builtin-function-map start
const BuiltinFunctionMap::Map& BuiltinFunctionMap::map() const {
constexpr std::size_t kMax = std::numeric_limits<std::size_t>::max();
// clang-format off
static const Map builtin_functions = {
... ...
{"start", {1, 1, {false, do_start}}},
... ...
};
// clang-format on
return builtin_functions;
}
我们看下 do_start()
:
// system/core/init/builtins.cpp
static Result<Success> do_start(const BuiltinArguments& args) {
Service* svc = ServiceList::GetInstance().FindService(args[1]); // 找到 zygote service 对应信息
if (!svc) return Error() << "service " << args[1] << " not found";
if (auto result = svc->Start(); !result) { // 启动对应的进程
return Error() << "Could not start service: " << result.error();
}
return Success();
}
do_start()
首先是通过 FindService()
去 service 数组
中遍历,根据名字匹配出对应的 service
,然后调用 service 的 Start()
函数。
最后,我们来看看 service.cpp
中定义 Start()
函数:
// system/core/init/service.cpp
Result<Success> Service::Start() {
... ...
pid_t pid = -1;
if (namespace_flags_) {
pid = clone(nullptr, nullptr, namespace_flags_ | SIGCHLD, nullptr);
} else {
pid = fork(); // 从 init 进程中,fork 出 zygote 进程
}
... ...
}
Start()
函数主要是 fork 出一个新进程
,然后执行 service 对应的二进制文件,并将参数传递进去,下面我们以 init.zygote64.rc
为例进行分析。
init.zygote64.rc 启动文件的地址为 /system/bin/app_process64
。
app_process64
对应的代码定义在 frameworks/base/cmds/app_process
目录下。
我们来看看对应的 Android.mk
:
// frameworks/base/cmds/app_process
LOCAL_PATH:= $(call my-dir)
... ...
app_process_src_files := \
app_main.cpp \
... ...
LOCAL_MODULE:= app_process
LOCAL_MULTILIB := both
LOCAL_MODULE_STEM_32 := app_process32
LOCAL_MODULE_STEM_64 := app_process64
... ...
其实不管是 app_process
、app_process32
还是 app_process64
,对应的源文件都是 app_main.cpp
。
接下来我们就看看 app_process
对应的 main 函数
,该函数定义于 app_main.cpp
中。
在
app_main.cpp
的main()
函数中,主要做的事情就是参数解析
。这个函数有两种
启动模式:
✎ zygote 模式
,也就是初始化 zygote 进程,传递的参数有 “–start-system-server --socket-name=zygote”,前者表示启动 SystemServer,后者指定 socket 的名称。
✎ application 模式
,也就是启动普通应用程序,传递的参数有 "class 名字"以及 “class 带的参数”。
两者最终都是调用 AppRuntime 对象
的 start() 函数
,加载 ZygoteInit
或 RuntimeInit
两个 Java 类,并将之前整理的参数传入进去。
接下来正式开始 main
函数的分析。
// frameworks/base/cmds/app_process/app_main.cpp
int main(int argc, char* const argv[])
{
// 将参数 argv 放到 argv_String 字符串中,然后打印出来
// 之前 start zygote 传入的参数是 -Xzygote /system/bin --zygote --start-system-server
if (!LOG_NDEBUG) {
String8 argv_String;
for (int i = 0; i < argc; ++i) {
argv_String.append("\"");
argv_String.append(argv[i]);
argv_String.append("\" ");
}
ALOGV("app_process main with argv: %s", argv_String.string());
}
// AppRuntime 定义于 app_main.cpp 中,继承自 AndroidRuntime
// 就是对 Android 运行环境的一种抽象,类似于 java 虚拟机对 Java 程序的作用
AppRuntime runtime(argv[0], computeArgBlockSize(argc, argv));
argc--;
argv++;
// 这两个参数是 Java 程序需要依赖的 Jar 包,相当于 import
const char* spaced_commands[] = { "-cp", "-classpath" };
bool known_command = false;
int i;
for (i = 0; i < argc; i++) { // 找到解析参数的起点
if (known_command == true) { // 将 spaced_commands 中的参数额外加入 VM
runtime.addOption(strdup(argv[i]));
ALOGV("app_process main add known option '%s'", argv[i]);
known_command = false;
continue;
}
for (int j = 0;
j < static_cast<int>(sizeof(spaced_commands) / sizeof(spaced_commands[0]));
++j) {
// 比较参数是否是 spaced_commands 中的参数
if (strcmp(argv[i], spaced_commands[j]) == 0) {
known_command = true;
ALOGV("app_process main found known command '%s'", argv[i]);
}
}
// 如果参数第一个字符是'-',直接跳出循环,之前传入的第一个参数是 -Xzygote,所以执行到这儿就跳出了
if (argv[i][0] != '-') {
break;
}
if (argv[i][1] == '-' && argv[i][2] == 0) {
++i; // Skip --.
break;
}
runtime.addOption(strdup(argv[i]));
ALOGV("app_process main add option '%s'", argv[i]);
}
// 从这里其实可以看出,通过 app_main 可以启动 zygote、system-server 及普通 apk 进程
bool zygote = false;
bool startSystemServer = false;
bool application = false;
String8 niceName; // app_process 的名称改为 zygote
String8 className; // 启动 apk 进程时,对应的类名
++i;
// 跳过一个参数,之前跳过了 -Xzygote,这里继续跳过 /system/bin ,也就是所谓的 "parent dir"
while (i < argc) { // 开始解析输入参数
const char* arg = argv[i++];
if (strcmp(arg, "--zygote") == 0) { // 表示是 zygote 启动模式
zygote = true;
niceName = ZYGOTE_NICE_NAME; // 这个值根据平台可能是 zygote64 或 zygote
} else if (strcmp(arg, "--start-system-server") == 0) {
startSystemServer = true; // init.zygote.rc 中定义,启动 zygote 后会启动 system-server
} else if (strcmp(arg, "--application") == 0) {
application = true; // 表示是 application 启动模式,也就是普通应用程序
} else if (strncmp(arg, "--nice-name=", 12) == 0) {
niceName.setTo(arg + 12); // 进程别名,可以自己指定进程名
} else if (strncmp(arg, "--", 2) != 0) {
className.setTo(arg); // 与 --application 配置,启动指定的类,application 启动的 class
break;
} else {
--i;
break;
}
}
// 准备参数
Vector<String8> args;
if (!className.isEmpty()) { // className 不为空,说明是 application 启动模式
args.add(application ? String8("application") : String8("tool"));
runtime.setClassNameAndArgs(className, argc - i, argv + i);
... ...
} else { // zygote 启动模式
// We're in zygote mode.
maybeCreateDalvikCache(); // 创建 Dalvik 的缓存目录并定义权限
if (startSystemServer) { // 增加 start-system-server 参数
args.add(String8("start-system-server"));
}
char prop[PROP_VALUE_MAX]; // 获取平台对应的 abi 信息
if (property_get(ABI_LIST_PROPERTY, prop, NULL) == 0) {
LOG_ALWAYS_FATAL("app_process: Unable to determine ABI list from property %s.",
ABI_LIST_PROPERTY);
return 11;
}
String8 abiFlag("--abi-list="); // 参数需要制定 abi
abiFlag.append(prop);
args.add(abiFlag); // 加入 --abi-list= 参数
for (; i < argc; ++i) {
args.add(String8(argv[i])); // 将剩下的参数加入 args
}
}
if (!niceName.isEmpty()) { // 将 app_process 的进程名,替换为 niceName
runtime.setArgv0(niceName.string(), true /* setProcName */);
}
if (zygote) { // 调用 Runtime 的 start 函数, 启动 ZygoteInit
runtime.start("com.android.internal.os.ZygoteInit", args, zygote);
} else if (className) { // 启动 zygote 没有进入这个分支
// 但这个分支说明,通过配置 init.rc 文件,其实是可以不通过 zygote 来启动一个进程,
// 如果是 application 启动模式,则加载 RuntimeInit。
runtime.start("com.android.internal.os.RuntimeInit", args, zygote);
} else {
// error 情况
fprintf(stderr, "Error: no class name or --zygote supplied.\n");
app_usage();
LOG_ALWAYS_FATAL("app_process: no class name or --zygote supplied.");
}
}
现在我们知道 Zygote
是通过 runtime.start()
函数启动,此处的 runtime
是 AppRuntime
。
由于 AppRuntime
继承自 AndroidRuntime
,且没有重写 start()
方法,因此 zygote
的流程进入到了 AndroidRuntime.cpp
。
// frameworks/base/cmds/app_process/app_main.cpp
class AppRuntime : public AndroidRuntime
{
public:
AppRuntime(char* argBlockStart, const size_t argBlockLength)
: AndroidRuntime(argBlockStart, argBlockLength)
, mClass(NULL)
{
}
... ...
}
接下来,我们来看看 AndroidRuntime.start()
函数的流程。
// frameworks/base/core/jni/AndroidRuntime.cpp
void AndroidRuntime::start(const char* className, const Vector<String8>& options, bool zygote)
{
... ... // 打印一些日志,获取 ANDROID_ROOT 环境变量
/* start the virtual machine */
JniInvocation jni_invocation;
jni_invocation.Init(NULL); // 初始化 JNI,加载 libart.so
JNIEnv* env;
// 创建虚拟机,其中大多数参数由系统属性决定,最终 startVm 利用 JNI_CreateJavaVM 创建出虚拟机
if (startVm(&mJavaVM, &env, zygote) != 0) {
return;
}
// 回调 AppRuntime 的 onVmCreated 函数
// 对于 zygote 进程的启动流程而言,无实际操作,表示虚拟创建完成,但是里面是空实现
onVmCreated(env);
... ...
}
// frameworks/base/core/jni/AndroidRuntime.cpp
void AndroidRuntime::start(const char* className, const Vector<String8>& options, bool zygote)
{
... ...
/* 01. 创建 Java 虚拟机 */
/*
* Register android functions.
*/
if (startReg(env) < 0) { // 注册 JNI 函数
ALOGE("Unable to register all android natives\n");
return;
}
... ...
}
startReg()
首先是设置了 Android 创建线程的处理函数
,然后创建了一个 200 容量的局部引用作用域,用于确保不会出现 OutOfMemoryException
,最后就是调用 register_jni_procs()
进行 JNI 注册。
我们跟进源码看下:
// frameworks/base/core/jni/AndroidRuntime.cpp
/*static*/ int AndroidRuntime::startReg(JNIEnv* env)
{
ATRACE_NAME("RegisterAndroidNatives");
// 定义 Android 创建线程的 func:javaCreateThreadEtc,这个函数内部是通过 Linux 的 clone 来创建线程的
androidSetCreateThreadFunc((android_create_thread_fn) javaCreateThreadEtc);
ALOGV("--- registering native functions ---\n");
env->PushLocalFrame(200); // 创建一个 200 容量的局部引用作用域,这个局部引用其实就是局部变量
if (register_jni_procs(gRegJNI, NELEM(gRegJNI), env) < 0) { // 注册 JNI 函数
env->PopLocalFrame(NULL);
return -1;
}
env->PopLocalFrame(NULL); // 释放局部引用作用域
return 0;
}
从上述代码可以看出,startReg()
函数中主要是通过 register_jni_procs()
来 注册 JNI 函数
。其中,gRegJNI
是一个全局数组,该数组的定义如下:
// frameworks/base/core/jni/AndroidRuntime.cpp
static const RegJNIRec gRegJNI[] = { // 里面就是一堆函数指针
REG_JNI(register_com_android_internal_os_RuntimeInit),
REG_JNI(register_com_android_internal_os_ZygoteInit_nativeZygoteInit),
REG_JNI(register_android_os_SystemClock),
REG_JNI(register_android_util_EventLog),
REG_JNI(register_android_util_Log),
... ...
};
我们挑一个 register_com_android_internal_os_ZygoteInit_nativeZygoteInit
,这实际上是自定义 JNI
函数并进行 动态注册
的标准写法。
内部是调用 JNI 的 RegisterNatives
,这样注册后,Java 类 ZygoteInit
的 native
方法 nativeZygoteInit
就会调用 com_android_internal_os_ZygoteInit_nativeZygoteInit
函数。
// frameworks/base/core/jni/AndroidRuntime.cpp
int register_com_android_internal_os_ZygoteInit_nativeZygoteInit(JNIEnv* env)
{
const JNINativeMethod methods[] = {
{ "nativeZygoteInit", "()V",
(void*) com_android_internal_os_ZygoteInit_nativeZygoteInit },
};
return jniRegisterNativeMethods(env, "com/android/internal/os/ZygoteInit",
methods, NELEM(methods));
}
REG_JNI
对应的 宏定义
及 RegJNIRec
结构体的定义为:
#ifdef NDEBUG
#define REG_JNI(name) { name }
struct RegJNIRec {
int (*mProc)(JNIEnv*);
};
#else
#define REG_JNI(name) { name, #name }
struct RegJNIRec {
int (*mProc)(JNIEnv*);
const char* mName;
};
#endif
根据宏定义可以看出,宏 REG_JNI
将得到函数名;定义 RegJNIRec
数组时,函数名被赋值给 RegJNIRec
结构体,于是每个函数名被强行转换为函数指针
。
因此,register_jni_procs()
的 参数
就是一个 函数指针数组
,数组的大小
和 JNIEnv
。
我们来跟进一下 register_jni_procs()
函数:
// frameworks/base/core/jni/AndroidRuntime.cpp
static int register_jni_procs(const RegJNIRec array[], size_t count, JNIEnv* env)
{
for (size_t i = 0; i < count; i++) {
if (array[i].mProc(env) < 0) { // 调用 mProc
#ifndef NDEBUG
ALOGD("----------!!! %s failed to load\n", array[i].mName);
#endif
return -1;
}
}
return 0;
}
结合前面的分析,容易知道 register_jni_procs() 函数
,实际上就是调用 函数指针(mProc)对应的函数
,以进行实际的 JNI
函数注册`。
继续分析 AndroidRuntime.cpp
的 start
函数:
// frameworks/base/core/jni/AndroidRuntime.cpp
void AndroidRuntime::start(const char* className, const Vector<String8>& options, bool zygote)
{
/* 01. 创建 Java 虚拟机*/
/* 02. 注册 JNI 函数 */
--- --- --- --- --- --- ---
// 替换 string 为实际路径
// 例如:将 "com.android.internal.os.ZygoteInit" 替换为 "com/android/internal/os/ZygoteInit"
char* slashClassName = toSlashClassName(className != NULL ? className : "");
jclass startClass = env->FindClass(slashClassName); // 找到 class 文件
if (startClass == NULL) {
ALOGE("JavaVM unable to locate class '%s'\n", slashClassName);
/* keep going */
} else {
jmethodID startMeth = env->GetStaticMethodID(startClass, "main",
"([Ljava/lang/String;)V"); // 通过反射找到 ZygoteInit 的 main 函数
if (startMeth == NULL) {
ALOGE("JavaVM unable to find main() in '%s'\n", className);
/* keep going */
} else {
env->CallStaticVoidMethod(startClass, startMeth, strArray); // 调用 ZygoteInit 的 main() 函数
... ...
}
}
free(slashClassName);
ALOGD("Shutting down VM\n");
if (mJavaVM->DetachCurrentThread() != JNI_OK) // 退出当前线程
ALOGW("Warning: unable to detach main thread\n");
if (mJavaVM->DestroyJavaVM() != 0) // 创建一个线程,该线程会等待所有子线程结束后关闭虚拟机
ALOGW("Warning: VM did not shut down cleanly\n");
}
在 main()
函数最后,将 通过反射调用 ZygoteInit 的 main() 方法
。
至此,zygote 进程正式进入了 java 世界。
其实我们仔细想一想,就会觉得 zygote 的整个流程实际上是非常符合实际情况的。
1、在 Android 中,每个进程都运行在对应的虚拟机上,因此 zygote 首先就负责创建出虚拟机。
2、然后,为了反射调用 java 代码,必须有对应的 JNI 函数,于是 zygote 进行了 JNI 函数的注册。
3、当一切准备妥当后,zygote 进程才进入到了 java 世界。
现在我们跟进 ZygoteInit
的 main()
函数。
// frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
public class ZygoteInit {
... ...
public static void main(String argv[]) {
ZygoteServer zygoteServer = new ZygoteServer(); // 创建 ZygoteServer 对象
// 调用 native 函数,确保当前没有其它线程在运行,主要还是处于安全的考虑
ZygoteHooks.startZygoteNoThreadCreation();
... ...
Runnable caller;
try {
... ...
RuntimeInit.enableDdms();
boolean startSystemServer = false;
String socketName = "zygote";
String abiList = null;
boolean enableLazyPreload = false;
// 解析参数,得到上述变量的值
for (int i = 1; i < argv.length; i++) {
if ("start-system-server".equals(argv[i])) {
startSystemServer = true;
} else if ("--enable-lazy-preload".equals(argv[i])) {
enableLazyPreload = true;
} else if (argv[i].startsWith(ABI_LIST_ARG)) {
abiList = argv[i].substring(ABI_LIST_ARG.length());
} else if (argv[i].startsWith(SOCKET_NAME_ARG)) {
socketName = argv[i].substring(SOCKET_NAME_ARG.length());
} else {
throw new RuntimeException("Unknown command line argument: " + argv[i]);
}
}
final boolean isPrimaryZygote = zygoteSocketName.equals(Zygote.PRIMARY_SOCKET_NAME);
if (abiList == null) {
throw new RuntimeException("No ABI list supplied.");
}
if (!enableLazyPreload) {
bootTimingsTraceLog.traceBegin("ZygotePreload");
EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_START,
SystemClock.uptimeMillis());
preload(bootTimingsTraceLog); // 默认情况,预加载信息
EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_END,
SystemClock.uptimeMillis());
bootTimingsTraceLog.traceEnd(); // ZygotePreload
} else {
// 延迟预加载,变更 Zygote 进程优先级为 NORMAL 级别,第一次 fork 时才会 preload
Zygote.resetNicePriority();
}
... ...
if (startSystemServer) {
Runnable r = forkSystemServer(abiList, socketName, zygoteServer); // fork systemserver
if (r != null) {
r.run();
return;
}
}
Log.i(TAG, "Accepting command socket connections");
caller = zygoteServer.runSelectLoop(abiList); // zygote 进程进入无限循环,处理请求
} catch (Throwable ex) {
throw ex;
} finally {
zygoteServer.closeServerSocket();
}
if (caller != null) {
caller.run();
}
}
}
Zygote.main()
函数除了安全相关的内容外,最主要的工作就是 注册 server socket
、预加载
、启动 systemserver
及 进入无限循环处理请求消息
。
我们看看 预加载
的逻辑:
// frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
public class ZygoteInit {
static void preload(TimingsTraceLog bootTimingsTraceLog) {
beginPreload();
preloadClasses(); // 读取文件 system/etc/preloaded-classes,然后通过反射加载对应的类
cacheNonBootClasspathClassLoaders();
preloadResources(); // 负责加载一些常用的系统资源
nativePreloadAppProcessHALs();
maybePreloadGraphicsDriver();
preloadSharedLibraries(); // 一些必要库
preloadTextResources(); // 语言相关的字符信息
WebViewFactory.prepareWebViewInZygote();
endPreload();
warmUpJcaProviders(); // 安全相关的
sPreloadComplete = true;
}
}
为了让系统实际运行时更加流畅,在 zygote 启动时候,调用 preload()
函数进行了一些 预加载操作
。
Android 通过 Zygote fork
的方式创建 子进程
。Zygote 进程预加载这些类和资源,在 fork 子进程时,仅需要做一个复制即可。这样可以节约子进程的启动时间。
同时,根据 fork 的 copy-on-write
机制,有些类如果不做改变,甚至都不用复制,子进程可以和父进程共享这部分数据,从而省去不少内存的占用。
再来看看启动 SystemServer
的流程:
// frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
public class ZygoteInit {
private static Runnable forkSystemServer(String abiList, String socketName,
ZygoteServer zygoteServer) {
long capabilities = posixCapabilitiesAsBits(
OsConstants.CAP_IPC_LOCK,
OsConstants.CAP_KILL,
OsConstants.CAP_NET_ADMIN,
OsConstants.CAP_NET_BIND_SERVICE,
OsConstants.CAP_NET_BROADCAST,
OsConstants.CAP_NET_RAW,
OsConstants.CAP_SYS_MODULE,
OsConstants.CAP_SYS_NICE,
OsConstants.CAP_SYS_PTRACE,
OsConstants.CAP_SYS_TIME,
OsConstants.CAP_SYS_TTY_CONFIG,
OsConstants.CAP_WAKE_ALARM,
OsConstants.CAP_BLOCK_SUSPEND
);
... ...
/* Hardcoded command line to start the system server */
String args[] = {
"--setuid=1000",
"--setgid=1000",
"--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,1021,1023,"
+ "1024,1032,1065,3001,3002,3003,3006,3007,3009,3010",
"--capabilities=" + capabilities + "," + capabilities,
"--nice-name=system_server",
"--runtime-args",
"--target-sdk-version=" + VMRuntime.SDK_VERSION_CUR_DEVELOPMENT,
"com.android.server.SystemServer",
};
ZygoteArguments parsedArgs = null;
int pid;
try {
// 将上面准备的参数,按照 ZygoteArguments 的风格进行封装
parsedArgs = new ZygoteArguments(args);
Zygote.applyDebuggerSystemProperty(parsedArgs);
Zygote.applyInvokeWithSystemProperty(parsedArgs);
boolean profileSystemServer = SystemProperties.getBoolean(
"dalvik.vm.profilesystemserver", false);
if (profileSystemServer) {
parsedArgs.mRuntimeFlags |= Zygote.PROFILE_SYSTEM_SERVER;
}
/* Request to fork the system server process */
pid = Zygote.forkSystemServer( // 通过 fork "分裂" 出 system_server
parsedArgs.mUid, parsedArgs.mGid,
parsedArgs.mGids,
parsedArgs.mRuntimeFlags,
null,
parsedArgs.mPermittedCapabilities,
parsedArgs.mEffectiveCapabilities);
} catch (IllegalArgumentException ex) {
throw new RuntimeException(ex);
}
/* For child process */
if (pid == 0) {
if (hasSecondZygote(abiList)) { // 处理 32_64 和 64_32 的情况
waitForSecondaryZygote(socketName);
}
// fork 时会 copy socket,system server 需要主动关闭
zygoteServer.closeServerSocket();
return handleSystemServerProcess(parsedArgs);
}
return null;
}
}
创建出 SystemServer
进程后,调用 ZygoteServer.runSelectLoop()
,处理 server socket 收到的命令
。
// frameworks/base/core/java/com/android/internal/os/ZygoteServer.java
class ZygoteServer {
Runnable runSelectLoop(String abiList) {
ArrayList<FileDescriptor> socketFDs = new ArrayList<FileDescriptor>();
ArrayList<ZygoteConnection> peers = new ArrayList<ZygoteConnection>();
socketFDs.add(mZygoteSocket.getFileDescriptor()); // 首先将 server socket 加入到 socketFDs
peers.add(null);
while (true) {
fetchUsapPoolPolicyPropsWithMinInterval();
int[] usapPipeFDs = null;
StructPollfd[] pollFDs = null; // 每次循环,都重新创建需要监听的 pollFds
... ...
int pollIndex = 0;
for (FileDescriptor socketFD : socketFDs) {
pollFDs[pollIndex] = new StructPollfd();
pollFDs[pollIndex].fd = socketFD;
pollFDs[pollIndex].events = (short) POLLIN; // 关注事件到来
++pollIndex;
}
... ...
try {
Os.poll(pollFDs, -1); // 等待事件到来
} catch (ErrnoException ex) {
throw new RuntimeException("poll failed", ex);
}
boolean usapPoolFDRead = false;
// 注意这里是倒序的,即优先处理已建立链接的信息,后处理新建链接的请求
while (--pollIndex >= 0) {
if ((pollFDs[pollIndex].revents & POLLIN) == 0) {
continue;
}
// server socket 最先加入 fds, 因此这里是 server socket 收到数据
if (pollIndex == 0) {
// Zygote server socket
// 收到新的建立通信的请求,建立通信连接
ZygoteConnection newPeer = acceptCommandPeer(abiList);
// 加入到 peers 和 socketFDs, 即下一次也开始监听
peers.add(newPeer);
socketFDs.add(newPeer.getFileDescriptor());
} else if (pollIndex < usapPoolEventFDIndex) {
... ... // 其他通信连接收到数据
}
}
... ...
}
}
}
从上面代码可知,初始时 socketFDs 中仅有 server socket
,因此当有数据到来时,将执行 i 等于 0 的分支。此时,显然是需要创建新的通信连接,因此 acceptCommandPeer()
将被调用。
我们看看 acceptCommandPeer()
方法:
// frameworks/base/core/java/com/android/internal/os/ZygoteServer.java
class ZygoteServer {
private ZygoteConnection acceptCommandPeer(String abiList) {
try {
// socket 编程中,accept() 调用主要用在基于连接的套接字类型,
// 比如 SOCK_STREAM 和 SOCK_SEQPACKET,它提取出所监听套接字的等待连接队列中第一个连接请求,
// 创建一个新的套接字,并返回指向该套接字的文件描述符,新建立的套接字不在监听状态,
// 原来所监听的套接字的状态也不受 accept() 调用的影响。
return createNewConnection(mZygoteSocket.accept(), abiList);
} catch (IOException ex) {
throw new RuntimeException(
"IOException during accept()", ex);
}
}
protected ZygoteConnection createNewConnection(LocalSocket socket, String abiList)
throws IOException {
return new ZygoteConnection(socket, abiList);
}
}
从上面的代码,可以看出 acceptCommandPeer()
调用了 mZygoteSocket.accpet
函数。于是当新的连接建立时,zygote
将会创建出一个 新的 socket
与其通信,并将该 socket
加入到 socketFDs
中。因此,一旦通信连接建立后,socketFDs
中将会包含有多个 socket
。
当 poll
监听到这一组 sockets
上有数据到来时,就会从阻塞中恢复,于是我们需要判断到底是哪个 socket
收到了数据。
Zygote 启动流程到此结束,共做了如下几件事:
✎ 1. 创建 AppRuntime
并调用其 start()
方法,启动 Zygote
进程。
✎ 2. 创建 JavaVM
并为 JavaVM 注册 JNI
。
✎ 3. 通过 JNI 调用 ZygoteInit
的 main()
函数进入 Zygote 的 Java 层
。
✎ 4. 通过 registerZygoteSocket()
函数创建 服务端 Socket
,预加载类和资源,并通过 runSelectLoop()
函数等待如 ActivityManagerService
等的请求。
✎ 5. 启动 SystemServer
进程。