前段时间在看Android9.0的PackageManagerService的源码,看着看着就在想PackageManagerService是如何被启动的,发现它是被SystemServer启动的,然后就又想SystemServer又是怎么被创建的呢,就一步步跟代码,发现SystemServer是从zygote进程fork出来的,想把最近了解的内容总结下,于是就有了这篇文章(如果再跟下去你会发现zygote又是从init进程fork出来的)

zygote 是什么

简单地说,它是一个进程。如果稍微再详细点的话,它是孵化其他Android应用进程的进程。

zygote进程如何被创建的

​ 前面我们知道zygote进程能孵化其他Android进程,那么zygote进程又是由谁孵化的呢?我们知道Android是基于Linux内核,而Linux的第一个用户级进程为init进程(PID等于1),所以很容易联想到zygote进程很有可能就是init进程孵化出来的,实际上也确实如此。下面我们就看下zygote孵化的过程,过程主要包括:

  • init 进程解析init.rc文件
  • zygote孵化

init进程解析

system/core/init/init.cppsystem/core/init/init.hsystem/core/init/action_manager.hsystem/core/init/action_manager.cppsystem/core/init/service.hsystem/core/init/service.cppsystem/core/init/parser.hsystem/core/init/parser.cpp

下面就是init进程解析init.rc文件时与zygote相关的过程:

//system/core/init/init.cppint main(int argc, char** argv) {    //省略部分无关代码......    const BuiltinFunctionMap function_map;    Action::set_function_map(&function_map);    subcontexts = InitializeSubcontexts();    ActionManager& am = ActionManager::GetInstance();    ServiceList& sm = ServiceList::GetInstance();    //开始解析初始化脚本文件    LoadBootScripts(am, sm);    // Turning this on and letting the INFO logging be discarded adds 0.2s to    // Nexus 9 boot time, so it's disabled by default.    if (false) DumpState();    //省略部分无关代码......    return 0;}static void LoadBootScripts(ActionManager& action_manager, ServiceList& service_list) {    //创建不通的解析器,包括ActionParser、ImportParser和ServiceParser    Parser parser = CreateParser(action_manager, service_list);    //判断是否有配置ro.boot.init_rc属性    std::string bootscript = GetProperty("ro.boot.init_rc", "");    if (bootscript.empty()) {        //如果没有配置ro.boot.init_rc属性,则解析init.rc        parser.ParseConfig("/init.rc");        //后面的几个if语句判断对应的路径是否有配置文件,如果有则把路径加入容器        if (!parser.ParseConfig("/system/etc/init")) {            late_import_paths.emplace_back("/system/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文件内容,由于篇幅原因,还是省略了部分内容;

#system/core/rootdir/init.rcimport /init.environ.rcimport /init.usb.rcimport /init.${ro.hardware}.rcimport /vendor/etc/init/hw/init.${ro.hardware}.rcimport /init.usb.configfs.rcimport /init.${ro.zygote}.rcon early-init    # Set init and its forked children's oom_adj.    write /proc/1/oom_score_adj -1000    # Disable sysrq from keyboard    write /proc/sys/kernel/sysrq 0    # Set the security context of /adb_keys if present.    restorecon /adb_keys    # Set the security context of /postinstall if present.    restorecon /postinstall    # Mount cgroup mount point for cpu accounting    mount cgroup none /acct nodev noexec nosuid cpuacct    mkdir /acct/uid    # root memory control cgroup, used by lmkd    mkdir /dev/memcg 0700 root system    mount cgroup none /dev/memcg nodev noexec nosuid memory    # app mem cgroups, used by activity manager, lmkd and zygote    mkdir /dev/memcg/apps/ 0755 system system    # cgroup for system_server and surfaceflinger    mkdir /dev/memcg/system 0550 system system    start ueventd    .......

文件开头import了其他的rc文件,init.${ro.zygote}.rc就是zygote的有关的初始化脚本,ro.zygote属性可以通过getprop ro.zygote 查看机型对应的属性,比如下面就是32位的机型初始化脚本文件。

#system/core/rootdir/init.zygote32.rcservice zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server    class main    priority -20    user root    group root readproc reserved_disk    socket zygote stream 660 root system    onrestart write /sys/android_power/request_state wake    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

service的格式如下:

service   [  ]*   

zygote进程的启动就是通过service命令“/system/bin/app_process -Xzygote /system/bin --zygote --start-system-server”。有关rc文件的更多内容可以参考system/core/init/README.md文件

在前面的时序图中,我们了解到解析过程会调用Parser::ParseData函数,在这个过程中就是根据不同类型采用对应的parser来解析

//system/core/init/parse.cppvoid Parser::ParseData(const std::string& filename, const std::string& data, size_t* parse_errors) {    // TODO: Use a parser with const input and remove this copy    std::vector data_copy(data.begin(), data.end());    data_copy.push_back('\0');    parse_state state;    state.line = 0;    state.ptr = &data_copy[0];    state.nexttoken = 0;    SectionParser* section_parser = nullptr;    int section_start_line = -1;    std::vector args;    auto end_section = [&] {        if (section_parser == nullptr) return;        if (auto result = section_parser->EndSection(); !result) {            (*parse_errors)++;            LOG(ERROR) << filename << ": " << section_start_line << ": " << result.error();        }        section_parser = nullptr;        section_start_line = -1;    };    for (;;) {        switch (next_token(&state)) {            case T_EOF:                end_section();                return;            case T_NEWLINE:                state.line++;                if (args.empty()) break;                // If we have a line matching a prefix we recognize, call its callback and unset any                // current section parsers.  This is meant for /sys/ and /dev/ line entries for                // uevent.                for (const auto& [prefix, callback] : line_callbacks_) {                    if (android::base::StartsWith(args[0], prefix)) {                        end_section();                        if (auto result = callback(std::move(args)); !result) {                            (*parse_errors)++;                            LOG(ERROR) << filename << ": " << state.line << ": " << result.error();                        }                        break;                    }                }                //section_parsers_是个map集合,数据初始化在init.cpp的CreateParser()函数中                if (section_parsers_.count(args[0])) {                    end_section();                    section_parser = section_parsers_[args[0]].get();                    section_start_line = state.line;                    if (auto result =                            section_parser->ParseSection(std::move(args), filename, state.line);                        !result) {                        (*parse_errors)++;                        LOG(ERROR) << filename << ": " << state.line << ": " << result.error();                        section_parser = nullptr;                    }                } else if (section_parser) {                    if (auto result = section_parser->ParseLineSection(std::move(args), state.line);                        !result) {                        (*parse_errors)++;                        LOG(ERROR) << filename << ": " << state.line << ": " << result.error();                    }                }                args.clear();                break;            case T_TEXT:                args.emplace_back(state.text);                break;        }    }}
//system/core/init/service.cppResult ServiceParser::ParseLineSection(std::vector&& args, int line) {    return service_ ? service_->ParseLine(std::move(args)) : Success();}Result Service::ParseLine(const std::vector& args) {    static const OptionParserMap parser_map;    auto parser = parser_map.FindFunction(args);    if (!parser) return parser.error();    //执行真正的命令,比如zygote.rc的“/system/bin/app_process -Xzygote /system/bin --zygote --start-system-server”    return std::invoke(*parser, this, args);}

最后附上解析器相关的类关系图

zygote启动

 在了解init.rc解析后,我们再看下zygote进程对应的app_main.cpp文件的main函数执行过程

//app_main.cppint main(int argc, char* const argv[]){    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对象runtime(AppRuntime继承自AndroidRuntime)    AppRuntime runtime(argv[0], computeArgBlockSize(argc, argv));    //省略部分代码    //...........    if (zygote) {        //这里会调用ZygoteInit.java的main()方法        runtime.start("com.android.internal.os.ZygoteInit", args, zygote);    } else if (className) {        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.");    }}

 main()函数主要作用是创建java虚拟机并调用ZygoteInit.java类的main()方法,而又是怎么实现在C++中调用到Java层的ZygoteInit.main()方法的呢,这就要看下runtime.start("com.android.internal.os.ZygoteInit", args, zygote)具体的实现,看下start()函数的具体实现

//AndroidRuntime.cppvoid AndroidRuntime::start(const char* className, const Vector& options, bool zygote){    ALOGD(">>>>>> START %s uid %d <<<<<<\n",            className != NULL ? className : "(unknown)", getuid());    static const String8 startSystemServer("start-system-server");    /*     * 'startSystemServer == true' means runtime is obsolete and not run from     * init.rc anymore, so we print out the boot start event here.     */    for (size_t i = 0; i < options.size(); ++i) {        if (options[i] == startSystemServer) {           /* 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)));        }    }    const char* rootDir = getenv("ANDROID_ROOT");    if (rootDir == NULL) {        rootDir = "/system";        if (!hasDir("/system")) {            LOG_FATAL("No root directory specified, and /android does not exist.");            return;        }        setenv("ANDROID_ROOT", rootDir, 1);    }    //const char* kernelHack = getenv("LD_ASSUME_KERNEL");    //ALOGD("Found LD_ASSUME_KERNEL='%s'\n", kernelHack);    /* start the virtual machine */    JniInvocation jni_invocation;    jni_invocation.Init(NULL);    JNIEnv* env;    //创建虚拟机    if (startVm(&mJavaVM, &env, zygote) != 0) {        return;    }    onVmCreated(env);    /*     * Register android functions.     */    if (startReg(env) < 0) {        ALOGE("Unable to register all android natives\n");        return;    }    /*     * We want to call main() with a String array with arguments in it.     * At present we have two arguments, the class name and an option string.     * Create an array to hold them.     */    jclass stringClass;    jobjectArray strArray;    jstring classNameStr;    stringClass = env->FindClass("java/lang/String");    assert(stringClass != NULL);    strArray = env->NewObjectArray(options.size() + 1, stringClass, NULL);    assert(strArray != NULL);    classNameStr = env->NewStringUTF(className);    assert(classNameStr != NULL);    env->SetObjectArrayElement(strArray, 0, classNameStr);    for (size_t i = 0; i < options.size(); ++i) {        jstring optionsStr = env->NewStringUTF(options.itemAt(i).string());        assert(optionsStr != NULL);        env->SetObjectArrayElement(strArray, i + 1, optionsStr);    }    /*     * Start VM.  This thread becomes the main thread of the VM, and will     * not return until the VM exits.     */    char* slashClassName = toSlashClassName(className != NULL ? className : "");    jclass startClass = env->FindClass(slashClassName);    if (startClass == NULL) {        ALOGE("JavaVM unable to locate class '%s'\n", slashClassName);        /* keep going */    } else {        //JNI的方式得到startClass的main()方法的jmethodID        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 {            //这里就实现了调用startClass的main()方法            env->CallStaticVoidMethod(startClass, startMeth, strArray);#if 0            if (env->ExceptionCheck())                threadExitUncaughtException(env);#endif        }    }    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");}

zygote 作用

接下来,我们看下ZygoteInit.main()方法里面都做了些什么

//ZygoteInit.javapublic static void main(String argv[]) {       ZygoteServer zygoteServer = new ZygoteServer();       // Mark zygote start. This ensures that thread creation will throw       // an error.       ZygoteHooks.startZygoteNoThreadCreation();       // Zygote goes into its own process group.       try {           Os.setpgid(0, 0);       } catch (ErrnoException ex) {           throw new RuntimeException("Failed to setpgid(0,0)", ex);       }       final Runnable caller;       try {           // Report Zygote start time to tron unless it is a runtime restart           if (!"1".equals(SystemProperties.get("sys.boot_completed"))) {               MetricsLogger.histogram(null, "boot_zygote_init",                       (int) SystemClock.elapsedRealtime());           }           String bootTimeTag = Process.is64Bit() ? "Zygote64Timing" : "Zygote32Timing";           TimingsTraceLog bootTimingsTraceLog = new TimingsTraceLog(bootTimeTag,                   Trace.TRACE_TAG_DALVIK);           bootTimingsTraceLog.traceBegin("ZygoteInit");           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]);               }           }           if (abiList == null) {               throw new RuntimeException("No ABI list supplied.");           }           //创建socket           zygoteServer.registerServerSocket(socketName);           // In some configurations, we avoid preloading resources and classes eagerly.           // In such cases, we will preload things prior to our first fork.           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.resetNicePriority();           }           // Do an initial gc to clean up after startup           bootTimingsTraceLog.traceBegin("PostZygoteInitGC");           gcAndFinalize();           bootTimingsTraceLog.traceEnd(); // PostZygoteInitGC           bootTimingsTraceLog.traceEnd(); // ZygoteInit           // Disable tracing so that forked processes do not inherit stale tracing tags from           // Zygote.           Trace.setTracingEnabled(false, 0);           // Zygote process unmounts root storage spaces.           Zygote.nativeUnmountStorageOnInit();           // Set seccomp policy           Seccomp.setPolicy();           ZygoteHooks.stopZygoteNoThreadCreation();           if (startSystemServer) {               //fork SystemServer进程               Runnable r = forkSystemServer(abiList, socketName, 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.           caller = zygoteServer.runSelectLoop(abiList);       } catch (Throwable ex) {           Log.e(TAG, "System zygote died with exception", ex);           throw ex;       } finally {           zygoteServer.closeServerSocket();       }       // We're in the child process and have exited the select loop. Proceed to execute the       // command.       if (caller != null) {           caller.run();       }   }

在ZygoteInit.main()方法中主要做了两件事:

  • fork SystemServer进程;

  • 在一个循环中等待命令fork 新的进程,该功能的实现是在ZygoteServer.runSelectLoop()方法中,该方法是一个无限循环,等待socket连接,然后根据连接中的参数fork新的进程,fork的过程与 fork SystemServer的过程类似

fork SystemServer

在ZygoteInit.forkSystemServer()方法中会设置SystemServer的参数,然后调用Zygote.forkSystemServer()方法

//ZygoteInit.javaprivate 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       );       /* Containers run without this capability, so avoid setting it in that case */       if (!SystemProperties.getBoolean(PROPERTY_RUNNING_IN_CONTAINER, false)) {           capabilities |= posixCapabilitiesAsBits(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,1032,3001,3002,3003,3006,3007,3009,3010",           "--capabilities=" + capabilities + "," + capabilities,           "--nice-name=system_server",           "--runtime-args",           "com.android.server.SystemServer",       };       ZygoteConnection.Arguments parsedArgs = null;       int pid;       try {           parsedArgs = new ZygoteConnection.Arguments(args);           ZygoteConnection.applyDebuggerSystemProperty(parsedArgs);           ZygoteConnection.applyInvokeWithSystemProperty(parsedArgs);           /* Request to fork the system server process */           //fork systemserver,Zygote.forSystemServer()调用了Zygote.nativeForkSystemServer()方法,该JNI方法具体实现在com_android_internal_os_Zygote.cpp中           pid = Zygote.forkSystemServer(                   parsedArgs.uid, parsedArgs.gid,                   parsedArgs.gids,                   parsedArgs.debugFlags,                   null,                   parsedArgs.permittedCapabilities,                   parsedArgs.effectiveCapabilities);       } catch (IllegalArgumentException ex) {           throw new RuntimeException(ex);       }       /* For child process */       //pid =0 表示当前在子进程中       if (pid == 0) {           if (hasSecondZygote(abiList)) {               waitForSecondaryZygote(socketName);           }           zygoteServer.closeServerSocket();           return handleSystemServerProcess(parsedArgs);       }       return null;   }

Zygote.forkSystemServer()具体在com_android_internal_os_Zygote.cpp实现就不展开了,最终就是通过调用bionic(/bionic/libc/bionic/fork.cpp)库中的fork.cpp中的fork()函数。有点一点需要注意,当调用一次fork()函数会在父进程和子进程中各返回一次,在子进程的返回的是0,在父进程中返回的是子进程id。有关fork()函数请参考fork()函数,最后附上zygote main()函数的时序图。

更多相关文章

  1. C语言函数的递归(上)
  2. Android(安卓)指纹识别开发实例
  3. Android(安卓)Service生命周期及用法
  4. [Android(安卓)API学习]Data Storage胡乱翻译(1)
  5. Android(安卓)Studio启动崩溃的问题:Start Failed Internal error
  6. Android内存泄漏检测工具大全
  7. Google_android_JNI使用方法
  8. Android之ContentProvider源码解析
  9. Android(安卓)Bluetooth

随机推荐

  1. Android:shape的使用详解(1)
  2. Android(安卓)Studio的Gradle文件方法说
  3. android log 学习
  4. Android核心入门分析
  5. Android(安卓)之ndk开发
  6. Android的消息机制
  7. Android(安卓)Testing和Instrumentation
  8. android 虚拟按键遮挡布局
  9. android环境变量配置
  10. Android调Ajax和动态添加JS中的token(And