前言
因为源码剖析的代码量比拟大,大部分博客网站的内容显示页面都比拟窄,显示进去的成果都异样俊俏,所以您也能够间接查看 《 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 |
Zygote 简介
在 Android 零碎中,JavaVM(Java 虚拟机)
、应用程序过程
以及运行零碎要害服务的 SystemServer 过程
都是由 Zygote
来创立的,咱们也将它称为 孵化器
。它通过 fock
(复制过程)的模式来创立 "应用程序过程"
和 "SystemServer 过程"
,因为 Zygote 过程在启动时会创立 JavaVM,因而通过 fock 而创立的 “应用程序过程” 和 “SystemServer 过程” 能够在外部获取一个 JavaVM 的实例拷贝
。
一、Zygote
1.1 触发
在后面剖析 init 过程 时,咱们晓得 init 过程启动后,会解析 init.rc 文件,而后创立和加载 "service"
字段指定的过程。zygote 过程就是以这种形式被 init 过程加载的。
在 system/core/rootdir/init.rc
中,能够看到:
<code class="cpp">// 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} 由厂商定义,与平台相干
1.2 init.xx.rc
在不同的平台(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 的代码如下所示:
<code class="cpp">/* * 过程名称是 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
1.3 start zygote
既然定义了此 service
用于启动 Zygote
,那么是在什么中央启动的呢?在探讨 init 的时候,咱们剖析过:init 过程启动的最初,会解决 late-init
事件。
<code class="java">// 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 配置文件中,咱们找到如下代码:
<code class="cpp">// 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
中。
<code class="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()
:
<code class="cpp">// 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()
函数:
<code class="cpp">// 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
为例进行剖析。
二、app_process
init.zygote64.rc 启动文件的地址为 /system/bin/app_process64
。
app_process64
对应的代码定义在 frameworks/base/cmds/app_process
目录下。
咱们来看看对应的 Android.mk
:
<code class="cpp">// 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
中。
2.1 app_main.main()
在
app_main.cpp
的main()
函数中,次要做的事件就是参数解析
。这个函数有两种
启动模式:
✎ zygote 模式
,也就是初始化 zygote 过程,传递的参数有 “–start-system-server –socket-name=zygote”,前者示意启动 SystemServer,后者指定 socket 的名称。
✎ application 模式
,也就是启动一般应用程序,传递的参数有 “class 名字”以及 “class 带的参数”。
两者最终都是调用 AppRuntime 对象
的 start() 函数
,加载 ZygoteInit
或 RuntimeInit
两个 Java 类,并将之前整顿的参数传入进去。
接下来正式开始 main
函数的剖析。
<code class="java">// 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
。
2.2 AndroidRuntime
因为 AppRuntime
继承自 AndroidRuntime
,且没有重写 start()
办法,因而 zygote
的流程进入到了 AndroidRuntime.cpp
。
<code class="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()
函数的流程。
2.2.1 创立 Java 虚拟机
<code class="java">// 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); ... ... }
2.2.2 注册 JNI 函数
<code class="java">// 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 注册。
咱们跟进源码看下:
<code class="java">// 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
是一个全局数组,该数组的定义如下:
<code class="java">// 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
函数。
<code class="java">// 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
构造体的定义为:
<code class="cpp">#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()
函数:
<code class="cpp">// 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
函数注册`。
2.2.3 反射启动 ZygoteInit
持续剖析 AndroidRuntime.cpp
的 start
函数:
<code class="cpp">// 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
当初咱们跟进 ZygoteInit
的 main()
函数。
<code class="java">// 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
及 进入有限循环解决申请音讯
。
3.1 预加载
咱们看看 预加载
的逻辑:
<code class="java">// 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
机制,有些类如果不做扭转,甚至都不必复制,子过程能够和父过程共享这部分数据,从而省去不少内存的占用。
3.2 启动 SystemServer 过程
再来看看启动 SystemServer
的流程:
<code class="java">// 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; } }
3.3 解决申请信息
创立出 SystemServer
过程后,调用 ZygoteServer.runSelectLoop()
,解决 server socket 收到的命令
。
<code class="java">// 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()
办法:
<code class="java">// 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
过程。