前言
因为源码剖析的代码量比拟大,大部分博客网站的内容显示页面都比拟窄,显示进去的成果都异样俊俏,所以您也能够间接查看《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
中,能够看到:
// 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 的代码如下所示:
/*
* 过程名称是 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
事件。
// 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
为例进行剖析。
二、app_process
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
中。
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
函数的剖析。
// 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
。
// 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 虚拟机
// 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 函数
// 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
函数注册 `。
2.2.3 反射启动 ZygoteInit
持续剖析 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
当初咱们跟进 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
及 进入有限循环解决申请音讯
。
3.1 预加载
咱们看看 预加载
的逻辑:
// 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
的流程:
// 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 收到的命令
。
// 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
过程。