目录
1.什么是Zygote?
Zygote是Android系统创建的第一个Java进程,它是所有Java进程的父进程。Zygote进程作为Socket的Server端,接收处理系统中创建进程的请求。Android中的应用进程的创建都是应用进程通过Binder发送请求给SystemServer,SystemServer再发送Socket消息给Zygote进程,统一由Zygote进程创建出来的。整个过程如下图所示:
进程的创建采用Zygote创建的话有以下几点原因:
1.Zygote进程在启动的时候会创建一个虚拟机实例,因此通过Zygote进程创建的子进程都会继承这个虚拟机实例,app中的Java代码都可以得到翻译执行。
2.Zygote创建的子进程还可以获得一个Binder线程池,这样进程之间就可以通过Binder进行跨进程通信了。
2. Zygote脚本启动
init进程是Android用户空间的第一个进程,也就是说其他所有的进程都是直接或者间接由init进程fork出来的。Zygote也不例外,它是在系统启动过程中由init进程创建的。所以讲解Zygote的创建需要由init进程的创建展开。
Android 10.0 之后init的入口函数由init.cpp变为了main.cpp,并且将各个阶段的代码进行了 划分,使其结构更清晰。
//system/core/init/main.cpp
51 int main(int argc, char** argv) {
52 #if __has_feature(address_sanitizer)
53 __asan_set_error_report_callback(AsanReportCallback);
54 #endif
55
56 if (!strcmp(basename(argv[0]), "ueventd")) {
57 return ueventd_main(argc, argv);
58 }
59
60 if (argc > 1) {
61 if (!strcmp(argv[1], "subcontext")) {
62 android::base::InitLogging(argv, &android::base::KernelLogger);
63 const BuiltinFunctionMap function_map;
64
65 return SubcontextMain(argc, argv, &function_map);
66 }
67
68 if (!strcmp(argv[1], "selinux_setup")) {
69 return SetupSelinux(argv);
70 }
71
72 if (!strcmp(argv[1], "second_stage")) {
73 return SecondStageMain(argc, argv);
74 }
75 }
76
77 return FirstStageMain(argc, argv);
78 }
通过对system/core/init/README.md的阅读可以知道main函数会被执行多次,启动的顺序是ueventd_main->FirstStageMain
->SetupSelinux->SecondStageMain。
1)ueventd_main主要功能:
1.解析ueventd相关rc文件,管理设备节点权限
2.Cold boot,递归扫描/sys目录,根据uevent文件,静态创建设备节点
3.Hot plug, 获取内核uevent 事件,动态创建设备节点。
2)FirstStageMain主要功能:
1.创建文件系统目录并挂载相关的文件系统
2.屏蔽标准的输入输出/初始化内核log系统
3)SetupSeLinux主要功能:
1.初始化SElinux,加载SELinux规则,配置SELinux相关log输出,并启动第二阶段。
4)SecondStageMain主要功能(重点关注部分):
1.创建进程会话秘钥并初始化属性系统
2.进行SELinux第二阶段并恢复一些文件安全上下文
3.新建epoll并初始化子进程中止信号处理函数
4.启动属性服务
5.解析init.rc等文件,启动其他进程
SecondStageMain的部分具体通过代码来看一下:
//system/core/init/init.cpp
618 int SecondStageMain(int argc, char** argv) {
619 if (REBOOT_BOOTLOADER_ON_PANIC) {
620 InstallRebootSignalHandlers();
621 }
........
//系统初始化
643 property_init();
674 // Now set up SELinux for second stage.
675 SelinuxSetupKernelLogging();
676 SelabelInitialize();
677 SelinuxRestoreContext();
678
//注册信号处理
679 Epoll epoll;
680 if (auto result = epoll.Open(); !result) {
681 PLOG(FATAL) << result.error();
682 }
683
684 InstallSignalFdHandler(&epoll);
........
//启动系统属性服务
690 StartPropertyService(&epoll);
........
//解析.rc文件
706 LoadBootScripts(am, sm);
........
//加入触发early-init语句
721 am.QueueEventTrigger("early-init");
........
//加入触发init语句
742 am.QueueEventTrigger("init");
........
//加入触发late-init语句
756 if (bootmode == "charger") {
757 am.QueueEventTrigger("charger");
758 } else {
759 am.QueueEventTrigger("late-init");
760 }
........
//执行所有触发器队列中Action command的执行函数
776 if (!(waiting_for_prop || Service::is_exec_service_running())) {
777 am.ExecuteOneCommand();
778 }
LoadBootScripts(am, sm)会执行解析init.rc的操作,init.rc是一个配置文件,它内部是由Android初始化语言(Android Init Language)编写的脚本,它主要包含五种类型的语句:Action,Commands,Services,Options和Import。本篇博客主要探讨Zygote的启动流程,关于初始化语言的用法可以参考源码中的README,里面有详细的使用说明。
Zygote的启动脚本是通过Import语句引入到init.rc中的。
//system/core/rootdir/init.rc
10 import /vendor/etc/init/hw/init.${ro.hardware}.rc
11 import /init.usb.configfs.rc
12 import /init.${ro.zygote}.rc
这里根据属性ro.zygote的内容来引入不同的Zygote启动脚本。Android 5.0以后,Android开始支持64位编译,Zygote进程也随之引入了32/64位的区别。所以,这里通过ro.zygote属性来控制启动不同版本的Zygote进程。
ro.zygote属性会有四种不同的值:
zygote32:代表32位模式
zygote32_64:代表32模式为主,64位模式为辅
zygote64:代表64位模式
zygote64_32:代表64模式为主,32位模式为辅
Zygote启动脚本的路径为system/core/rootdir。
这里我们以64位处理器为例,init.zygote64.rc代码如下:
//system/core/rootdir/init.zygote64.rc
1 service zygote /system/bin/app_process64 -Xzygote /system/bin --zygote --start-system-server
2 class main
3 priority -20
4 user root
5 group root readproc reserved_disk
6 socket zygote stream 660 root system
7 socket usap_pool_primary stream 660 root system
8 onrestart write /sys/android_power/request_state wake
9 onrestart write /sys/power/state on
10 onrestart restart audioserver
11 onrestart restart cameraserver
12 onrestart restart media
13 onrestart restart netd
14 onrestart restart wificond
15 writepid /dev/cpuset/foreground/tasks
为了分析Zygote的创建,我们需要看下Services类型的语句格式:
service <name> <pathname> [ <argument> ]* //service名字 执行路径 参数
<option> //option是service的修饰词,影响什么时候,如何启动service
<option> ...
Android中有专门的函数对service进行解析,一个是ParseSection,它会解析service的rc文件,它的主要作用就是搭建service的框架,另一个函数ParseLineSection用来解析子项。
有了services类型语句格式的介绍,我们就可以知道Zygote进行的名字为zygote,执行路径为/system/bin/app_process64。注册了service之后,就是在一个合适的时机对它进行调用。我们回到我们上面init.rc中
//解析.rc文件
706 LoadBootScripts(am, sm);
........
//加入触发early-init语句
721 am.QueueEventTrigger("early-init");
........
//加入触发init语句
742 am.QueueEventTrigger("init");
........
//加入触发late-init语句
756 if (bootmode == "charger") {
757 am.QueueEventTrigger("charger");
758 } else {
759 am.QueueEventTrigger("late-init");
760 }
........
//执行所有触发器队列中Action command的执行函数
//这个地方就会依次执行我们上面加入的触发语句,也就是依次执行early-init,init,late-init
776 if (!(waiting_for_prop || Service::is_exec_service_running())) {
777 am.ExecuteOneCommand();
778 }
start Zygote的操作在late-init中,我们看下late-init
//system/core/rootdir/init.rc
314 # Mount filesystems and start core system services.
315 on late-init
316 trigger early-fs
........
339 # Now we can start zygote for devices with file based encryption
340 trigger zygote-start
........
//triger zygote
626 # It is recommended to put unnecessary data/ initialization from post-fs-data
627 # to start-zygote in device's init.rc to unblock zygote start.
628 on zygote-start && property:ro.crypto.state=unencrypted
629 # A/B update verifier that marks a successful boot.
630 exec_start update_verifier_nonencrypted
631 start netd
632 start zygote
633 start zygote_secondary
634
635 on zygote-start && property:ro.crypto.state=unsupported
636 # A/B update verifier that marks a successful boot.
637 exec_start update_verifier_nonencrypted
638 start netd
639 start zygote
640 start zygote_secondary
641
642 on zygote-start && property:ro.crypto.state=encrypted && property:ro.crypto.type=file
643 # A/B update verifier that marks a successful boot.
644 exec_start update_verifier_nonencrypted
645 start netd
646 start zygote
647 start zygote_secondary
start命令对应的执行函数为do_start,定义在platform/system/core/init/builtings.cpp,这个对应关系式在parseService的时候建立的。
//system/core/init/builtins.cpp
1193 // Builtin-function-map start
1194 const BuiltinFunctionMap::Map& BuiltinFunctionMap::map() const {
1195 constexpr std::size_t kMax = std::numeric_limits<std::size_t>::max();
1196 // clang-format off
1197 static const Map builtin_functions = {
1198 {"bootchart", {1, 1, {false, do_bootchart}}},
1199 {"chmod", {2, 2, {true, do_chmod}}},
1200 {"chown", {2, 3, {true, do_chown}}},
1201 {"class_reset", {1, 1, {false, do_class_reset}}},
1202 {"class_reset_post_data", {1, 1, {false, do_class_reset_post_data}}},
1203 {"class_restart", {1, 1, {false, do_class_restart}}},
1204 {"class_start", {1, 1, {false, do_class_start}}},
1205 {"class_start_post_data", {1, 1, {false, do_class_start_post_data}}},
1206 {"class_stop", {1, 1, {false, do_class_stop}}},
1207 {"copy", {2, 2, {true, do_copy}}},
1208 {"domainname", {1, 1, {true, do_domainname}}},
1209 {"enable", {1, 1, {false, do_enable}}},
........
1244 {"start", {1, 1, {false, do_start}}},
........
715 static Result<Success> do_start(const BuiltinArguments& args) {
716 Service* svc = ServiceList::GetInstance().FindService(args[1]);
717 if (!svc) return Error() << "service " << args[1] << " not found";
718 if (auto result = svc->Start(); !result) {
719 return Error() << "Could not start service: " << result.error();
720 }
721 return Success();
722 }
//system/core/init/service.cpp
887 Result<Success> Service::Start() {
888 if (is_updatable() && !ServiceList::GetInstance().IsServicesUpdated()) {
889 ServiceList::GetInstance().DelayService(*this);
890 return Error() << "Cannot start an updatable service '" << name_
891 << "' before configs from APEXes are all loaded. "
892 << "Queued for execution.";
893 }
........
//从init进程中fork出zygote进程
958 pid_t pid = -1;
959 if (namespace_flags_) {
960 pid = clone(nullptr, nullptr, namespace_flags_ | SIGCHLD, nullptr);
961 } else {
962 pid = fork();
963 }
964
........
//为zygote创建socket,详情见下
1001 std::for_each(descriptors_.begin(), descriptors_.end(),
1002 std::bind(&DescriptorInfo::CreateAndPublish, std::placeholders::_1, scon));
........
//启动zygote,详情见下
1057 if (!ExpandArgsAndExecv(args_, sigstop_)) {
1058 PLOG(ERROR) << "cannot execve('" << args_[0] << "')";
1059 }
1060
1061 _exit(127);
1062 }
先分析下zygote socket的创建。
//system/core/init/descriptors.cpp
52 void DescriptorInfo::CreateAndPublish(const std::string& globalContext) const {
53 // Create
54 const std::string& contextStr = context_.empty() ? globalContext : context_;
//在/dev/socket目录下面创建文件一个文件
55 int fd = Create(contextStr);
56 if (fd < 0) return;
57
//这个key()为#define ANDROID_SOCKET_ENV_PREFIX "ANDROID_SOCKET_"
//所以最终publish的全称为ANDROID_SOCKET_zygote
59 std::string publishedName = key() + name_;
60 std::for_each(publishedName.begin(), publishedName.end(),
61 [] (char& c) { c = isalnum(c) ? c : '_'; });
62
63 std::string val = std::to_string(fd);
//将创建的socket的fd放入环境变量ANDROID_SOCKET_zygote中,此处要注意后面zygote进程中就是根据此来获取socket的fd的
64 setenv(publishedName.c_str(), val.c_str(), 1);
65
66 // make sure we don't close on exec
67 fcntl(fd, F_SETFD, 0);
68 }
socket的创建主要完成了两件事:
1.创建一个socket fd,并且将这个fd与某个文件(dev/socket/xx,xx就是上面列出的名字,比如zygote)绑定,然后根据init.rc里面的定义来设定相关的用户,组合权限,最后返回fd。
2.将socket名字(带ANDROID_SOCKET_前缀,比如ANDROID_SOCKET_zygote)和fd注册到init进程的环境变量里,这样所有其他进程(所有进程都是init的子进程)都可以通过getenv(name)获取fd。
继续Start的流程,最后执行
if (!ExpandArgsAndExecv(args_, sigstop_)) {
PLOG(ERROR) << "cannot execve('" << args_[0] << "')";
}
这里会执行service zygote /system/bin/app_process64 -Xzygote /system/bin --zygote --start-system-server正式开始zygote的启动。总结下以上流程:
3.Zygote进程启动
从最开始分析的init.zygote64.rc可以看出,zygote64启动文件的地址为app_process64,app_process64对应的代码定义在frameworks/base/cmds/app_process中,可以看到该目录下对应的Android.mk
//frameworks/base/cmds/app_process/Android.mk
1 LOCAL_PATH:= $(call my-dir)
2
3 app_process_common_shared_libs := \
4 libandroid_runtime \
5 libbinder \
6 libcutils \
7 libdl \
8 libhidlbase \
9 liblog \
10 libnativeloader \
11 libutils \
........
23 app_process_src_files := \
24 app_main.cpp \
........
45 LOCAL_MODULE:= app_process
........
不管是app_process,app_process32还是app_process64对应的源文件都是app_main.cpp,其中的main函数就是zygote
进程启动的入口函数,整个启动过程的时序图如下:
zygote启动过程中主要完成以下工作:
a.调用AndroidRuntime startVM()创建虚拟机
b.调用startReg()注册JNI函数
c.调用registerServerSocket建立socket通道,zygote作为服务端,用于响应客户端的请求。
d.preload()预加载通用类,drawable和color资源,openGL以及共享库以及WebView,用于提升app的启动速度。
e.startSystemServer创建system_server,以及各种系统进程。
f.最后调用 (),通过while循环,一直监听接收client端创建新进程的请求。
下面就按照时序图针对每一步骤进行详细介绍。
1.main函数,init进程通过init_zygotexx.rc启动zygote进程,入口app_main.cpp
//frameworks/base/cmds/app_process/app_main.cpp
173 int main(int argc, char* const argv[])
//zygote传入的参数argv为"Xzygote /system/bin --zygote --start-system-server --socket-name=zygote"
174 {
175 if (!LOG_NDEBUG) {
176 String8 argv_String;
177 for (int i = 0; i < argc; ++i) {
178 argv_String.append("\"");
179 argv_String.append(argv[i]);
180 argv_String.append("\" ");
181 }
182 ALOGV("app_process main with argv: %s", argv_String.string());
183 }
184
........
264 while (i < argc) {
265 const char* arg = argv[i++];
266 if (strcmp(arg, "--zygote") == 0) {
267 zygote = true;
//64位系统nice_name为zygote64,32位系统为zygote
268 niceName = ZYGOTE_NICE_NAME;
269 } else if (strcmp(arg, "--start-system-server") == 0) {
270 startSystemServer = true;
271 } else if (strcmp(arg, "--application") == 0) {
272 application = true;
273 } else if (strncmp(arg, "--nice-name=", 12) == 0) {
274 niceName.setTo(arg + 12);
275 } else if (strncmp(arg, "--", 2) != 0) {
276 className.setTo(arg);
277 break;
278 } else {
279 --i;
280 break;
281 }
282 }
........
285 if (!className.isEmpty()) {
286 // We're not in zygote mode, the only argument we need to pass
287 // to RuntimeInit is the application argument.
288 //
289 // The Remainder of args get passed to startup class main(). Make
290 // copies of them before we overwrite them with the process name.
291 args.add(application ? String8("application") : String8("tool"));
292 runtime.setClassNameAndArgs(className, argc - i, argv + i);
293
294 if (!LOG_NDEBUG) {
295 String8 restOfArgs;
296 char* const* argv_new = argv + i;
297 int argc_new = argc - i;
298 for (int k = 0; k < argc_new; ++k) {
299 restOfArgs.append("\"");
300 restOfArgs.append(argv_new[k]);
301 restOfArgs.append("\" ");
302 }
303 ALOGV("Class name = %s, args = %s", className.string(), restOfArgs.string());
304 }
305 } else {
306 // We're in zygote mode.
//进入zygote模式,新建Dalvik的缓存目录:/data/dalvik-cache
307 maybeCreateDalvikCache();
308
309 if (startSystemServer) {
310 args.add(String8("start-system-server"));
311 }
312
313 char prop[PROP_VALUE_MAX];
314 if (property_get(ABI_LIST_PROPERTY, prop, NULL) == 0) {
315 LOG_ALWAYS_FATAL("app_process: Unable to determine ABI list from property %s.",
316 ABI_LIST_PROPERTY);
317 return 11;
318 }
319
320 String8 abiFlag("--abi-list=");
321 abiFlag.append(prop);
322 args.add(abiFlag);
323
324 // In zygote mode, pass all remaining arguments to the zygote
325 // main() method.
326 for (; i < argc; ++i) {
327 args.add(String8(argv[i]));
328 }
329 }
330
331 if (!niceName.isEmpty()) {
//设置别名zygote/zygote64
332 runtime.setArgv0(niceName.string(), true /* setProcName */);
333 }
334
335 if (zygote) {
//如果是zygote模式,则加载ZygoteInit
336 runtime.start("com.android.internal.os.ZygoteInit", args, zygote);
337 } else if (className) {
//如果是application启动模式,则加载RuntimeInit
338 runtime.start("com.android.internal.os.RuntimeInit", args, zygote);
339 } else {
340 fprintf(stderr, "Error: no class name or --zygote supplied.\n");
341 app_usage();
342 LOG_ALWAYS_FATAL("app_process: no class name or --zygote supplied.");
343 }
344 }
2.start
//frameworks/base/core/jni/AndroidRuntime.cpp
1120 void AndroidRuntime::start(const char* className, const Vector<String8>& options, bool zygote)
1121 {
1122 ALOGD(">>>>>> START %s uid %d <<<<<<\n",
1123 className != NULL ? className : "(unknown)", getuid());
1124
1125 static const String8 startSystemServer("start-system-server");
1126
........
164 /* start the virtual machine */
1165 JniInvocation jni_invocation;
1166 jni_invocation.Init(NULL);
1167 JNIEnv* env;
//创建虚拟机(时序图步骤3),详情见下步骤3
1168 if (startVm(&mJavaVM, &env, zygote) != 0) {
1169 return;
1170 }
1171 onVmCreated(env);
1172
1173 /*
1174 * Register android functions.
1175 */
//注册jni(时序图步骤4),详情见下步骤4
1176 if (startReg(env) < 0) {
1177 ALOGE("Unable to register all android natives\n");
1178 return;
1179 }
........
if (startClass == NULL) {
1211 ALOGE("JavaVM unable to locate class '%s'\n", slashClassName);
1212 /* keep going */
1213 } else {
//反射调用ZygoteInit
1214 jmethodID startMeth = env->GetStaticMethodID(startClass, "main",
1215 "([Ljava/lang/String;)V");//通过反射找到ZygoteInit.main()
1216 if (startMeth == NULL) {
1217 ALOGE("JavaVM unable to find main() in '%s'\n", className);
1218 /* keep going */
1219 } else {
//调用ZygoteInit的main函数,详情见下步骤5
1220 env->CallStaticVoidMethod(startClass, startMeth, strArray);
1221
1222 #if 0
1223 if (env->ExceptionCheck())
1224 threadExitUncaughtException(env);
1225 #endif
1226 }
1227 }
1228 free(slashClassName);
1229
1230 ALOGD("Shutting down VM\n");
1231 if (mJavaVM->DetachCurrentThread() != JNI_OK)
1232 ALOGW("Warning: unable to detach main thread\n");
1233 if (mJavaVM->DestroyJavaVM() != 0)
1234 ALOGW("Warning: VM did not shut down cleanly\n");
1235 }
start()函数主要完成3件事:
a.调用startVm创建虚拟机
b.调用startReg注册JNI方法
c.启动Zygote进程
每一步骤的详细分析如下:
3.startVm
//frameworks/base/core/jni/AndroidRuntime.cpp
634 int AndroidRuntime::startVm(JavaVM** pJavaVM, JNIEnv** pEnv, bool zygote)
........
//jni检测功能,用于native层调用jni函数时进行常规检测
717 bool checkJni = false;
718 property_get("dalvik.vm.checkjni", propBuf, "");
719 if (strcmp(propBuf, "true") == 0) {
720 checkJni = true;
721 } else if (strcmp(propBuf, "false") != 0) {
722 /* property is neither true nor false; fall back on kernel parameter */
723 property_get("ro.kernel.android.checkjni", propBuf, "");
724 if (propBuf[0] == '1') {
725 checkJni = true;
726 }
727 }
728 ALOGV("CheckJNI is %s\n", checkJni ? "ON" : "OFF");
729 if (checkJni) {
730 /* extended JNI checking */
731 addOption("-Xcheck:jni");
732
733 /* with -Xcheck:jni, this provides a JNI function call trace */
734 //addOption("-verbose:jni");
735 }
........
//preloaded-classes文件内容是有WriePreloadedClassFile.java生成的
//预加载其中的classes提高系统性能
892 if (hasFile("/system/etc/boot-image.prof")) {
893 addOption("-Ximage-compiler-option");
894 addOption("--profile-file=/system/etc/boot-image.prof");
895 addOption("-Ximage-compiler-option");
896 addOption("--compiler-filter=speed-profile");
897 } else {
898 // Make sure there is a preloaded-classes file.
899 if (!hasFile("/system/etc/preloaded-classes")) {
900 ALOGE("Missing preloaded-classes file, /system/etc/preloaded-classes not found: %s\n",
901 strerror(errno));
902 return -1;
903 }
904 addOption("-Ximage-compiler-option");
905 addOption("--image-classes=/system/etc/preloaded-classes");
906
907 // If there is a dirty-image-objects file, push it.
908 if (hasFile("/system/etc/dirty-image-objects")) {
909 addOption("-Ximage-compiler-option");
910 addOption("--dirty-image-objects=/system/etc/dirty-image-objects");
911 }
912 }
........
//初始化虚拟机
1079 if (JNI_CreateJavaVM(pJavaVM, pEnv, &initArgs) < 0) {
1080 ALOGE("JNI_CreateJavaVM failed\n");
1081 return -1;
1082 }
1083
1084 return 0;
1085 }
4.startReg
startReg首先是设置了Android创建线程的处理函数,然后创建了一个200容量的局部引用域,用于确保不会出现OutMemoryException,最后调用register_jni_process进行JNI方法的注册。
//frameworks/base/core/jni/AndroidRuntime.cpp
1603 /*static*/ int AndroidRuntime::startReg(JNIEnv* env)
1604 {
1605 ATRACE_NAME("RegisterAndroidNatives");
1606 /*
1607 * This hook causes all future threads created in this process to be
1608 * attached to the JavaVM. (This needs to go away in favor of JNI
1609 * Attach calls.)
1610 */
//设置Android创建线程的函数javaCreateThreadEtc,这个函数内部是通过Linux的Clone创建线程的
1611 androidSetCreateThreadFunc((android_create_thread_fn) javaCreateThreadEtc);
1612
1613 ALOGV("--- registering native functions ---\n");
1614
1615 /*
1616 * Every "register" function calls one or more things that return
1617 * a local reference (e.g. FindClass). Because we haven't really
1618 * started the VM yet, they're all getting stored in the base frame
1619 * and never released. Use Push/Pop to manage the storage.
1620 */
//创建一个200容量的局部引用域
1621 env->PushLocalFrame(200);
1622
//注册JNI,详情见下4.1
1623 if (register_jni_procs(gRegJNI, NELEM(gRegJNI), env) < 0) {
1624 env->PopLocalFrame(NULL);
1625 return -1;
1626 }
//释放局部引用作用域
1627 env->PopLocalFrame(NULL);
1628
1629 //createJavaThread("fubar", quickTest, (void*) "hello");
1630
1631 return 0;
1632 }
4.1 register_jni_procs
//frameworks/base/core/jni/AndroidRuntime.cpp
1407 static int register_jni_procs(const RegJNIRec array[], size_t count, JNIEnv* env)
1408 {
1409 for (size_t i = 0; i < count; i++) {
1410 if (array[i].mProc(env) < 0) {//调用gRegJNI的mProc
1411 #ifndef NDEBUG
1412 ALOGD("----------!!! %s failed to load\n", array[i].mName);
1413 #endif
1414 return -1;
1415 }
1416 }
1417 return 0;
1418 }
//gRegJNI是一个全局数组,定义如下:
//frameworks/base/core/jni/AndroidRuntime.cpp
1420 static const RegJNIRec gRegJNI[] = {
1421 REG_JNI(register_com_android_internal_os_RuntimeInit),
1422 REG_JNI(register_com_android_internal_os_ZygoteInit_nativeZygoteInit),
1423 REG_JNI(register_android_os_SystemClock),
........
//frameworks/base/core/jni/AndroidRuntime.cpp
1392 #ifdef NDEBUG
1393 #define REG_JNI(name) { name }
1394 struct RegJNIRec {
1395 int (*mProc)(JNIEnv*);
1396 };
1397 #else
1398 #define REG_JNI(name) { name, #name }
1399 struct RegJNIRec {
1400 int (*mProc)(JNIEnv*);
1401 const char* mName;
1402 };
1403 #endif
由此可见array[i].mProc,调用mProc就等价于其参数名所指向的函数,例如REG_JNI(register_com_android_internal_os_ZygoteInit_nativeZygoteInit),就是调用register_com_android_internal_os_ZygoteInit_nativeZygoteInit
//frameworks/base/core/jni/AndroidRuntime.cpp
295 int register_com_android_internal_os_ZygoteInit_nativeZygoteInit(JNIEnv* env)
296 {
297 const JNINativeMethod methods[] = {
298 { "nativeZygoteInit", "()V",
299 (void*) com_android_internal_os_ZygoteInit_nativeZygoteInit },
300 };
//和com/android/internal/os/ZygoteInit.java的nativeZygoteInit对应
301 return jniRegisterNativeMethods(env, "com/android/internal/os/ZygoteInit",
302 methods, NELEM(methods));
303 }
5.反射调用ZygoteInit.main()
main函数主要执行下面4个操作
1.调用preload()预加载类和资源
2.调用ZygoteServer()创建Server端的socket /dev/socket/zygote,Socket等待AMS请求Zygote来创建新的应用程序进程。
3.调用forkSystemServer来启动SystemServer进程,接着SystemServer创建关键的系统进程。
4.调用runSelectLoop等待客户端请求。
//frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
819 public static void main(String argv[]) {
........
873 if (!enableLazyPreload) {
874 bootTimingsTraceLog.traceBegin("ZygotePreload");
875 EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_START,
876 SystemClock.uptimeMillis());
//预加载类和资源,详情见5.1
877 preload(bootTimingsTraceLog);
878 EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_END,
879 SystemClock.uptimeMillis());
880 bootTimingsTraceLog.traceEnd(); // ZygotePreload
881 } else {
882 Zygote.resetNicePriority();
883 }
........
899
//调用ZygoteServer构造函数,创建Server端socket,详情见5.2
900 zygoteServer = new ZygoteServer(isPrimaryZygote);
//启动systemServer,详情见5.3
902 if (startSystemServer) {
903 Runnable r = forkSystemServer(abiList, zygoteSocketName, zygoteServer);
904
905 // {@code r == null} in the parent (zygote) process, and {@code r != null} in the
906 // child (system_server) process.
907 if (r != null) {
908 r.run();
909 return;
910 }
911 }
913 Log.i(TAG, "Accepting command socket connections");
914
915 // The select loop returns early in the child process after a fork and
916 // loops forever in the zygote.
//zygote进入循环,等待client发出请求,详情见5.4
917 caller = zygoteServer.runSelectLoop(abiList);
918 } catch (Throwable ex) {
919 Log.e(TAG, "System zygote died with exception", ex);
920 throw ex;
921 } finally {
922 if (zygoteServer != null) {
923 zygoteServer.closeServerSocket();
924 }
925 }
926
927 // We're in the child process and have exited the select loop. Proceed to execute the
928 // command.
929 if (caller != null) {
930 caller.run();
931 }
932 }
5.1 preload预加载
为了让系统运行更流畅,一些系统中APP共享的资源会在zygote启动的时候进行预加载,这样在后面使用的时候就无需重复加载,加快了应用启动速度。Android通过zygote fork创建子进程,zygote进程预加载这些类和资源的时候,根据fork的copy-on-write机制可知,有些类如果不做改变,甚至不用复制。子进程可以和父进程共享这部分数据,从而省去不少内存的占用。
//frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
135 static void preload(TimingsTraceLog bootTimingsTraceLog) {
136 Log.d(TAG, "begin preload");
137 bootTimingsTraceLog.traceBegin("BeginPreload");
138 beginPreload();
139 bootTimingsTraceLog.traceEnd(); // BeginPreload
140 bootTimingsTraceLog.traceBegin("PreloadClasses");
//预加载类,这些类记录在framework/base/preloaded-classes
141 preloadClasses();
142 bootTimingsTraceLog.traceEnd(); // PreloadClasses
143 bootTimingsTraceLog.traceBegin("CacheNonBootClasspathClassLoaders");
144 cacheNonBootClasspathClassLoaders();
145 bootTimingsTraceLog.traceEnd(); // CacheNonBootClasspathClassLoaders
146 bootTimingsTraceLog.traceBegin("PreloadResources");
//加载图片,颜色等资源文件,部分定义在frameworks/base/ccore/res/res/values/array.xml
147 preloadResources();
148 bootTimingsTraceLog.traceEnd(); // PreloadResources
149 Trace.traceBegin(Trace.TRACE_TAG_DALVIK, "PreloadAppProcessHALs");
150 nativePreloadAppProcessHALs();
151 Trace.traceEnd(Trace.TRACE_TAG_DALVIK);
152 Trace.traceBegin(Trace.TRACE_TAG_DALVIK, "PreloadGraphicsDriver");
153 maybePreloadGraphicsDriver();
154 Trace.traceEnd(Trace.TRACE_TAG_DALVIK);
//加载library
155 preloadSharedLibraries();
//加载文字资源
156 preloadTextResources();
157 // Ask the WebViewFactory to do any initialization that must run in the zygote process,
158 // for memory sharing purposes.
//初始化webview
159 WebViewFactory.prepareWebViewInZygote();
160 endPreload();
161 warmUpJcaProviders();
162 Log.d(TAG, "end preload");
163
164 sPreloadComplete = true;
165 }
5.2 创建server socket
Android中采用LocalSocket,这是对Linux中Socket的封装,采用JNI方式调用,实现进程间通信。
客户端:
LocalSocket:客户端使用,创建套接字
LocalSocketAddress:套接字地址,即文件描述符
setSoTimeout:设置超时
connect:客户端主动向服务端请求连接
服务端:
LocalServerSocket:服务端使用,创建套接字同时指定文件描述符
accept:等待客户端连接
架构示意图如下:
//frameworks/base/core/java/com/android/internal/os/ZygoteServer.java
148 ZygoteServer(boolean isPrimaryZygote) {
149 mUsapPoolEventFD = Zygote.getUsapPoolEventFD();
150
151 if (isPrimaryZygote) {
//创建socket,并获取socket对象,socket name:zygote
152 mZygoteSocket = Zygote.createManagedSocketFromInitSocket(Zygote.PRIMARY_SOCKET_NAME);
//创建socket,并获取socket对象,socket name:usap_pool_primary
153 mUsapPoolSocket =
154 Zygote.createManagedSocketFromInitSocket(
155 Zygote.USAP_POOL_PRIMARY_SOCKET_NAME);
156 } else {
157 mZygoteSocket = Zygote.createManagedSocketFromInitSocket(Zygote.SECONDARY_SOCKET_NAME);
158 mUsapPoolSocket =
159 Zygote.createManagedSocketFromInitSocket(
160 Zygote.USAP_POOL_SECONDARY_SOCKET_NAME);
161 }
162
163 fetchUsapPoolPolicyProps();
164
165 mUsapPoolSupported = true;
166 }
//frameworks/base/core/java/com/android/internal/os/Zygote.java
161 private static final String ANDROID_SOCKET_PREFIX = "ANDROID_SOCKET_";
858 static LocalServerSocket createManagedSocketFromInitSocket(String socketName) {
859 int fileDesc;
//fullSocketName为ANDROID_SOCKET_zygote,注意这个名字和我们
//DescriptorInfo::CreateAndPublish注册的名字一致
860 final String fullSocketName = ANDROID_SOCKET_PREFIX + socketName;
861
862 try {
//init.zygote64.rc启动时注册了2个socket,分别是zygote,
//usap_pool_primary,在进程创建时会创建对应的文件描述符并加入到环境变量,
//这边根据name将它们取出
863 String env = System.getenv(fullSocketName);
864 fileDesc = Integer.parseInt(env);
865 } catch (RuntimeException ex) {
866 throw new RuntimeException("Socket unset or invalid: " + fullSocketName, ex);
867 }
868
869 try {
870 FileDescriptor fd = new FileDescriptor();
871 fd.setInt$(fileDesc);//获取zygote socket的文件描述符
872 return new LocalServerSocket(fd);//创建socket的服务端
873 } catch (IOException ex) {
874 throw new RuntimeException(
875 "Error building socket from file descriptor: " + fileDesc, ex);
876 }
877 }
//frameworks/base/core/java/android/net/LocalServerSocket.java
63 public LocalServerSocket(FileDescriptor fd) throws IOException
64 {
65 impl = new LocalSocketImpl(fd);
66 impl.listen(LISTEN_BACKLOG);
67 localAddress = impl.getSockAddress();
68 }
Socket Server端工作完成,等待client端的connect连接。
5.3启动SystemServer
//frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
724 private static Runnable forkSystemServer(String abiList, String socketName,
725 ZygoteServer zygoteServer) {
726 long capabilities = posixCapabilitiesAsBits(
727 OsConstants.CAP_IPC_LOCK,
728 OsConstants.CAP_KILL,
729 OsConstants.CAP_NET_ADMIN,
730 OsConstants.CAP_NET_BIND_SERVICE,
731 OsConstants.CAP_NET_BROADCAST,
732 OsConstants.CAP_NET_RAW,
733 OsConstants.CAP_SYS_MODULE,
734 OsConstants.CAP_SYS_NICE,
735 OsConstants.CAP_SYS_PTRACE,
736 OsConstants.CAP_SYS_TIME,
737 OsConstants.CAP_SYS_TTY_CONFIG,
738 OsConstants.CAP_WAKE_ALARM,
739 OsConstants.CAP_BLOCK_SUSPEND
740 );
741 /* Containers run without some capabilities, so drop any caps that are not available. */
742 StructCapUserHeader header = new StructCapUserHeader(
743 OsConstants._LINUX_CAPABILITY_VERSION_3, 0);
744 StructCapUserData[] data;
745 try {
746 data = Os.capget(header);
747 } catch (ErrnoException ex) {
748 throw new RuntimeException("Failed to capget()", ex);
749 }
750 capabilities &= ((long) data[0].effective) | (((long) data[1].effective) << 32);
751
752 /* Hardcoded command line to start the system server */
753 String args[] = {
754 "--setuid=1000",
755 "--setgid=1000",
756 "--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,1021,1023,"
757 + "1024,1032,1065,3001,3002,3003,3006,3007,3009,3010",
758 "--capabilities=" + capabilities + "," + capabilities,
759 "--nice-name=system_server",
760 "--runtime-args",
761 "--target-sdk-version=" + VMRuntime.SDK_VERSION_CUR_DEVELOPMENT,
762 "com.android.server.SystemServer",
763 };
764 ZygoteArguments parsedArgs = null;
765
766 int pid;
767
768 try {
769 parsedArgs = new ZygoteArguments(args);
770 Zygote.applyDebuggerSystemProperty(parsedArgs);
771 Zygote.applyInvokeWithSystemProperty(parsedArgs);
772
773 boolean profileSystemServer = SystemProperties.getBoolean(
774 "dalvik.vm.profilesystemserver", false);
775 if (profileSystemServer) {
776 parsedArgs.mRuntimeFlags |= Zygote.PROFILE_SYSTEM_SERVER;
777 }
778
779 /* Request to fork the system server process */
//通过fork分裂出子进程system_server
780 pid = Zygote.forkSystemServer(
781 parsedArgs.mUid, parsedArgs.mGid,
782 parsedArgs.mGids,
783 parsedArgs.mRuntimeFlags,
784 null,
785 parsedArgs.mPermittedCapabilities,
786 parsedArgs.mEffectiveCapabilities);
787 } catch (IllegalArgumentException ex) {
788 throw new RuntimeException(ex);
789 }
790
791 /* For child process */
792 if (pid == 0) {
793 if (hasSecondZygote(abiList)) {
794 waitForSecondaryZygote(socketName);
795 }
796
797 zygoteServer.closeServerSocket();
//system server处理函数
798 return handleSystemServerProcess(parsedArgs);
799 }
800
801 return null;
802 }
关于SystemServer的启动我们会在后面用单独一篇博客来介绍。
5.4 runSelectLoop等待client端请求
创建出SystemServer进程后,zygote进程调用ZygoteServer中的runSelectLoop处理server socket收到的请求。
//frameworks/base/core/java/com/android/internal/os/ZygoteServer.java
373 Runnable runSelectLoop(String abiList) {
374 ArrayList<FileDescriptor> socketFDs = new ArrayList<FileDescriptor>();
375 ArrayList<ZygoteConnection> peers = new ArrayList<ZygoteConnection>();
376
377 socketFDs.add(mZygoteSocket.getFileDescriptor());
378 peers.add(null);
379
//无限循环用来等待AMS请求Zygote创建新的应用进程
380 while (true) {
........
431 try {
//轮询,处理pollFDs事件
432 Os.poll(pollFDs, -1);
433 } catch (ErrnoException ex) {
434 throw new RuntimeException("poll failed", ex);
435 }
436
437 boolean usapPoolFDRead = false;
438
439 while (--pollIndex >= 0) {
440 if ((pollFDs[pollIndex].revents & POLLIN) == 0) {
441 continue;
442 }
443
444 if (pollIndex == 0) {
445 // Zygote server socket
446 //客户端发出连接请求,调用server socket端的accpet函数。Zygote进程与AMS进程建立了连接
447 ZygoteConnection newPeer = acceptCommandPeer(abiList);
448 peers.add(newPeer);
449 socketFDs.add(newPeer.getFileDescriptor());
450
451 } else if (pollIndex < usapPoolEventFDIndex) {
//AMS向zygote发出创建新进程的请求
452 // Session socket accepted from the Zygote server socket
453
454 try {
455 ZygoteConnection connection = peers.get(pollIndex);
//创建新的应用程序进程
456 final Runnable command = connection.processOneCommand(this);
........
//frameworks/base/core/java/com/android/internal/os/ZygoteConnection.java
129 Runnable processOneCommand(ZygoteServer zygoteServer) {
........
//fork 子进程
67 pid = Zygote.forkAndSpecialize(parsedArgs.mUid, parsedArgs.mGid, parsedArgs.mGids,
268 parsedArgs.mRuntimeFlags, rlimits, parsedArgs.mMountExternal, parsedArgs.mSeInfo,
269 parsedArgs.mNiceName, fdsToClose, fdsToIgnore, parsedArgs.mStartChildZygote,
270 parsedArgs.mInstructionSet, parsedArgs.mAppDataDir, parsedArgs.mTargetSdkVersion);
........
应用进程的创建后面我们也会用单独的一篇博客来说明,本篇博客更多的是梳理zygote进程的启动流程。至此zygote进程的启动全部结束。