> 文章列表 > Android系统启动流程--zygote进程的启动流程

Android系统启动流程--zygote进程的启动流程

Android系统启动流程--zygote进程的启动流程

在上一篇init进程启动流程中已经提到,在init中会解析一个init.rc文件,解析后会执行其中的命令来启动zygote进程、serviceManager进程等,下面我们来看一下:

//文件路径:system/core/init/init.cppstatic void LoadBootScripts(ActionManager& action_manager, ServiceList& service_list) {//创建解析器Parser parser = CreateParser(action_manager, service_list);std::string bootscript = GetProperty("ro.boot.init_rc", "");if (bootscript.empty()) {//解析init.rc ,这个是手机设备上的路径,和源码中system/core/rootdir/init.rc是一个文件parser.ParseConfig("/system/etc/init/hw/init.rc");if (!parser.ParseConfig("/system/etc/init")) {late_import_paths.emplace_back("/system/etc/init");}// late_import is available only in Q and earlier release. As we don't// have system_ext in those versions, skip late_import for system_ext.parser.ParseConfig("/system_ext/etc/init");if (!parser.ParseConfig("/product/etc/init")) {late_import_paths.emplace_back("/product/etc/init");}if (!parser.ParseConfig("/odm/etc/init")) {late_import_paths.emplace_back("/odm/etc/init");}if (!parser.ParseConfig("/vendor/etc/init")) {late_import_paths.emplace_back("/vendor/etc/init");}} else {parser.ParseConfig(bootscript);}
}

我们来看一下这个init.rc中和zygote相关的部分:

#文件路径:system/core/rootdir/init.rc   或设备上 /system/etc/init/hw/init.rc#引入子rc文件,${ro.zygote}是一个变量,取值范围zygote32、zygote64、zygote32_64、zygote64_32,会根据实际设备是32位还是64位进行选择
import /system/etc/init/hw/init.${ro.zygote}.rc# Mount filesystems and start core system services.
on late-init# Now we can start zygote for devices with file based encryption#在init启动后的一个时机,触发启动zygote进程trigger zygote-starton zygote-start && property:ro.crypto.state=unencrypted# A/B update verifier that marks a successful boot.exec_start update_verifier_nonencryptedstart statsdstart netdstart zygote  #启动zygote进程,那么这个zygote是什么呢?start zygote_secondary#还记得文件开头处的import 引入的子rc文件吗?我们以init.zygote64.rc为例:
#文件路径: system/core/rootdir/init.zygote64.rc#service zygote 服务名为zygote
#对应的可执行程序路径:/system/bin/app_process64  (设备上的路径)
#-Xzygote /system/bin --zygote --start-system-server  执行app_process64时传入的参数
service zygote /system/bin/app_process64 -Xzygote /system/bin --zygote --start-system-serverclass mainpriority -20user root  #用户角色group root readproc reserved_disksocket zygote stream 660 root systemsocket usap_pool_primary stream 660 root system#如果意外挂掉需要重启的服务onrestart exec_background - system system -- /system/bin/vdc volume abort_fuseonrestart write /sys/power/state ononrestart restart audioserveronrestart restart cameraserveronrestart restart mediaonrestart restart netdonrestart restart wificondwritepid /dev/cpuset/foreground/tasks

和上一篇中的init一样,zygote进程也具化到了设备中的执行程序,即app_process,我们来看下他是由那个文件编译出来的。

//文件路径 frameworks/base/cmds/app_process/Android.bpcc_binary {name: "app_process",srcs: ["app_main.cpp"], //是同目录的app_main.cpp...
}

至于怎么去找这么文件的路径目前没有发现太好的办法,只能是多熟悉每一层的bp编译脚本+关键字搜索。

打开app_main.cpp文件:

//文件路径:framesworks/base/cmds/app_process/app_main.cpp//argv :-Xzygote /system/bin --zygote --start-system-server
int main(int argc, char* const argv[])
{//创建了android运行时环境AppRuntime runtime(argv[0], computeArgBlockSize(argc, argv));//根据传入的参数设置变量值bool zygote = false;bool startSystemServer = false;bool application = false;String8 niceName;String8 className;while (i < argc) {const char* arg = argv[i++];if (strcmp(arg, "--zygote") == 0) { //传入参数中有--zygote,所以zygote = truezygote = true;niceName = ZYGOTE_NICE_NAME;} else if (strcmp(arg, "--start-system-server") == 0) { //同理startSystemServer = truestartSystemServer = true;} else if (strcmp(arg, "--application") == 0) {application = true;} else if (strncmp(arg, "--nice-name=", 12) == 0) {niceName.setTo(arg + 12);} else if (strncmp(arg, "--", 2) != 0) {className.setTo(arg);break;} else {--i;break;}}Vector<String8> args;if (!className.isEmpty()) {...}else {// We're in zygote mode.maybeCreateDalvikCache();if (startSystemServer) { //上面已经赋值为true// args中又添加了这个参数args.add(String8("start-system-server"));}...// In zygote mode, pass all remaining arguments to the zygote// main() method.for (; i < argc; ++i) {args.add(String8(argv[i]));}}...if (zygote) {//启动运行时环境,这里就是有native转到到java层的入口,这也是为什么说zygote是java层进程的鼻祖runtime.start("com.android.internal.os.ZygoteInit", args, zygote);} else if (className) { //而这个分支是启动app相关的流程,可以先有个印象后续分析到应用的启动流程可能还会看到这里// 将上面的args参数数组传入runtime.start("com.android.internal.os.RuntimeInit", args, zygote);} else {fprintf(stderr, "Error: no class name or --zygote supplied.\\n");app_usage();LOG_ALWAYS_FATAL("app_process: no class name or --zygote supplied.");}
}

继续跟踪runtime.start()方法,runtime是AppRuntime类型,但AppRuntime并没有start(),因为是定义在AppRuntime的父类中,找到此方法看下具体操作:

//文件路径: frameworks/base/core/jni/AndroidRuntime.cpp
void AndroidRuntime::start(const char* className, const Vector<String8>& options, bool zygote)
{bool primary_zygote = false;/ 'startSystemServer == true' means runtime is obsolete and not run from* init.rc anymore, so we print out the boot start event here.*///根据options参数判断是否是第一次启动zygotefor (size_t i = 0; i < options.size(); ++i) {if (options[i] == startSystemServer) {primary_zygote = true;/* track our progress through the boot sequence */const int LOG_BOOT_PROGRESS_START = 3000;LOG_EVENT_LONG(LOG_BOOT_PROGRESS_START,  ns2ms(systemTime(SYSTEM_TIME_MONOTONIC)));}}//设置android root目录环境变量const char* rootDir = getenv("ANDROID_ROOT");if (rootDir == NULL) {rootDir = "/system";if (!hasDir("/system")) {LOG_FATAL("No root directory specified, and /system does not exist.");return;}setenv("ANDROID_ROOT", rootDir, 1);}JNIEnv* env;if (startVm(&mJavaVM, &env, zygote, primary_zygote) != 0) {  //启动虚拟机,设置虚拟机的参数默认值return;}if (startReg(env) < 0) {  //注册JNI方法,系统api中涉及的jni方法都是在这里注册的ALOGE("Unable to register all android natives\\n");return;}char* slashClassName = toSlashClassName(className != NULL ? className : "");jclass startClass = env->FindClass(slashClassName);if (startClass == NULL) {}else {jmethodID startMeth = env->GetStaticMethodID(startClass, "main","([Ljava/lang/String;)V");if (startMeth == NULL) {ALOGE("JavaVM unable to find main() in '%s'\\n", className);/* keep going */} else {//jni 执行ZygoteInit.java 的main()方法,由此过渡到java层env->CallStaticVoidMethod(startClass, startMeth, strArray);}}
}

这里放一张图用于表示进程与虚拟机的关系,即每个进程都有独立的虚拟机,而虚拟机就是一块大的内存区域,这块大内存又划分为堆、线程栈、方法区、程序计数器、本地方法栈等等更小的内存块。

 继续上面的流程,进入java层的com.android.internal.os.ZygoteInit的main()函数:

// 文件路径:frameworks\\base\\core\\java\\com\\android\\internal\\os\\ZygoteInit.javapublic static void main(String argv[]) {ZygoteServer zygoteServer = null;//根据传入的参数设置变量for (int i = 1; i < argv.length; i++) {if ("start-system-server".equals(argv[i])) { //由层传入,所以startSystemServer = truestartSystemServer = 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)) {zygoteSocketName = argv[i].substring(SOCKET_NAME_ARG.length());} else {throw new RuntimeException("Unknown command line argument: " + argv[i]);}}if (!enableLazyPreload) {bootTimingsTraceLog.traceBegin("ZygotePreload");EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_START,SystemClock.uptimeMillis());//预加载系统资源文件,应用进程都是zygote进程fork出来的,在此进行预加载就不用在应用进程中再去重复加载资源文件,提升应用启动速度preload(bootTimingsTraceLog);EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_END,SystemClock.uptimeMillis());bootTimingsTraceLog.traceEnd(); // ZygotePreload}...zygoteServer = new ZygoteServer(isPrimaryZygote);if (startSystemServer) {//启动SystemServer进程,有zygote fork而来Runnable r = forkSystemServer(abiList, zygoteSocketName, zygoteServer);// {@code r == null} in the parent (zygote) process, and {@code r != null} in the// child (system_server) process.if (r != null) {r.run();return;}}Log.i(TAG, "Accepting command socket connections");// The select loop returns early in the child process after a fork and// loops forever in the zygote.//死循环,等待Ams发出的创建应用进程的消息caller = zygoteServer.runSelectLoop(abiList);
}

zygote进程重要事项总结

c++层:

  1. 创建Android runtime
  2. 启动虚拟机
  3. 注册JNI方法
  4. 通过JNI调用ZygoteInit.java的main(),转入到java层

java层:

  1. 预加载一些系统资源,如一些java类,resources文件,Graphics驱动、hal层的资源、动态库相关的操作等等
  2. 创建zygoteServer 服务端socket,等待AMS发出的创建应用进程的消息。
  3. fork 出systemServer进程