ZygoteInit从c到java

作者: 简祖明 | 来源:发表于2019-08-26 17:51 被阅读7次

    1.Android启动流程

    image.png

    2.init.cpp

    // system\core\init\init.cpp
    int main(int argc, char** argv) {
      ...
      // 创建虚拟文件
      mount("tmpfs", "/dev", "tmpfs", MS_NOSUID, "mode=0755");
      mkdir("/dev/pts", 0755);
      mkdir("/dev/socket", 0755);
      ...
      // 属性服务
      property_init();
      start_property_service()
      ...
      // 解析init.rc文件
      Parser& parser = Parser::GetInstance();
      parser.AddSectionParser("service",std::make_unique<ServiceParser>());
      parser.AddSectionParser("on", std::make_unique<ActionParser>());
      parser.AddSectionParser("import", std::make_unique<ImportParser>());
      parser.ParseConfig("/init.rc");
    }
    

    相关知识点:

    • tmpfs,devpts,proc,sysfs 4类虚拟文件系统
    • property_service
    • SELinux SEAndroid安全机制
    • init.rc脚本文件

    3.init.rc文件

    init.rc是一个配置文件,内部由Android初始化语言编写(Android Init Language)编写的脚本,主要包含五种类型语句:Action、Command、Service、Option和Import。

    import /init.${ro.zygote}.rc
    因为Android5.0以后支持64位程序,为了相互兼容,所以${ro.zygote}会根据具体情况,被替换成zygote32.rczygote32_64.rczygote64.rczygote64_32.rc,区别是启动32位程序还是64位。其中32_64表示app_process32为主模式。

    // 进程名称zygote
    // 对应二进制文件/system/bin/app_process64
    // 参数
    service zygote /system/bin/app_process64 -Xzygote /system/bin --zygote --start-system-server
        class main
        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
        writepid /dev/cpuset/foreground/tasks
    

    zygote对应的二进制文件是 /system/bin/app_process64,
    对应的目录在platform/frameworks/base/cmds/app_process/Android.mk,

    include $(CLEAR_VARS)
    
    LOCAL_SRC_FILES:= \
        app_main.cpp
    
    LOCAL_SHARED_LIBRARIES := \
        libcutils \
        libutils \
        liblog \
        libbinder \
        libandroid_runtime \
        $(app_process_common_shared_libs) \
    
    LOCAL_WHOLE_STATIC_LIBRARIES := libsigchain
    
    LOCAL_LDFLAGS := -ldl -Wl,--version-script,art/sigchainlib/version-script.txt -Wl,--export-dynamic
    LOCAL_CPPFLAGS := -std=c++11
    
    LOCAL_MODULE := app_process__asan
    LOCAL_MULTILIB := both
    LOCAL_MODULE_STEM_32 := app_process32
    LOCAL_MODULE_STEM_64 := app_process64
    

    4.app_main.cpp

    int main(int argc, char* const argv[])
    {
         // 1.AppRuntime对象
        AppRuntime runtime(argv[0], computeArgBlockSize(argc, argv));
        
        // 2.解析参数
        while (i < argc) {
            const char* arg = argv[i++];
            if (strcmp(arg, "--zygote") == 0) {
                zygote = true;
                niceName = ZYGOTE_NICE_NAME;
            } else if (strcmp(arg, "--start-system-server") == 0) { //需要启动SystemServer
                startSystemServer = true;
            } else if (strcmp(arg, "--application") == 0) { //表示是application启动模式,也就是普通应用程序
                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;
            }
        }
        ...
        if (zygote) { // 如果是zygote启动模式,则加载ZygoteInit
            // 3.start
            runtime.start("com.android.internal.os.ZygoteInit", args, zygote);
        } 
    

    app_main.cpp的main方法主要做的事情:

    • 初始化AppRuntime;
    • 解析命令中参数;
    • 通过AppRuntime去启动ZygoteInit类

    相关知识点:
    init.rc启动一些重要的进程,每一个都是重要的知识点,比如

    • Service Manager管理binder进程通信
    • SufaceFlinger图形显示

    5.void AndroidRuntime::start();

    void AndroidRuntime::start(const char* className, const Vector<String8>& options, bool zygote)
    {
        ... 
        /* start the virtual machine */
        JniInvocation jni_invocation;
        jni_invocation.Init(NULL); //初始化JNI,加载libart.so
        JNIEnv* env;
        if (startVm(&mJavaVM, &env, zygote) != 0) { // 创建虚拟机
            return;
        }
        onVmCreated(env); // 表示虚拟创建完成
    
        /*
         * Register android functions.
         */
        if (startReg(env) < 0) { // 注册JNI函数
            ALOGE("Unable to register all android natives\n");
            return;
        }
        ... 
        // JNI方式调用ZygoteInit类的main函数
        jclass stringClass;
        jobjectArray strArray;
        jstring classNameStr;
    
        stringClass = env->FindClass("java/lang/String");
        strArray = env->NewObjectArray(options.size() + 1, stringClass, NULL);
        classNameStr = env->NewStringUTF(className);
        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);
        jclass startClass = env->FindClass(slashClassName);
      
        // 找到要启动的java类,然后调用其main方法
        jmethodID startMeth = env->GetStaticMethodID(startClass, "main",
                "([Ljava/lang/String;)V");
    
         env->CallStaticVoidMethod(startClass, startMeth, strArray);
    ...
    

    相关知识点:

    • jni基础知识及实现原理
    • 虚拟机(内存布局、垃圾回收、线程机制、指令优化等)

    5.1 JniInvocation::Init()

    bool JniInvocation::Init(const char* library) {
    #ifdef __ANDROID__
      char buffer[PROP_VALUE_MAX];
    #else
      char* buffer = NULL;
    #endif
      library = GetLibrary(library, buffer);
      // Load with RTLD_NODELETE in order to ensure that libart.so is not unmapped when it is closed.
      // This is due to the fact that it is possible that some threads might have yet to finish
      // exiting even after JNI_DeleteJavaVM returns, which can lead to segfaults if the library is
      // unloaded.
      const int kDlopenFlags = RTLD_NOW | RTLD_NODELETE;
      handle_ = dlopen(library, kDlopenFlags);
      if (handle_ == NULL) {
        if (strcmp(library, kLibraryFallback) == 0) {
          // Nothing else to try.
          ALOGE("Failed to dlopen %s: %s", library, dlerror());
          return false;
        }
        // Note that this is enough to get something like the zygote
        // running, we can't property_set here to fix this for the future
        // because we are root and not the system user. See
        // RuntimeInit.commonInit for where we fix up the property to
        // avoid future fallbacks. http://b/11463182
        ALOGW("Falling back from %s to %s after dlopen error: %s",
              library, kLibraryFallback, dlerror());
        library = kLibraryFallback;
        handle_ = dlopen(library, kDlopenFlags);
        if (handle_ == NULL) {
          ALOGE("Failed to dlopen %s: %s", library, dlerror());
          return false;
        }
      }
      if (!FindSymbol(reinterpret_cast<void**>(&JNI_GetDefaultJavaVMInitArgs_),
                      "JNI_GetDefaultJavaVMInitArgs")) {
        return false;
      }
      if (!FindSymbol(reinterpret_cast<void**>(&JNI_CreateJavaVM_),
                      "JNI_CreateJavaVM")) {
        return false;
      }
      if (!FindSymbol(reinterpret_cast<void**>(&JNI_GetCreatedJavaVMs_),
                      "JNI_GetCreatedJavaVMs")) {
        return false;
      }
      return true;
    }
    
    

    5.2 startVm

    int AndroidRuntime::startVm(JavaVM** pJavaVM, JNIEnv** pEnv, bool zygote)
    {
        JavaVMInitArgs initArgs;
        ...
        addOption("exit", (void*) runtime_exit); // 将参数放入mOptions数组中
        ...
        initArgs.version = JNI_VERSION_1_4;
        initArgs.options = mOptions.editArray();// 将mOptions赋值给initArgs
        initArgs.nOptions = mOptions.size();
        if (JNI_CreateJavaVM(pJavaVM, pEnv, &initArgs) < 0) { // 调用libart.so的JNI_CreateJavaVM函数
                ALOGE("JNI_CreateJavaVM failed\n");
                return -1;
        }
        return 0;
    }
    
    

    各种系统属性中读取一些参数,设置到AndroidRuntime的mOptions集合中存起来。
    然后调用之前从libart.so中找到JNI_CreateJavaVM函数,并传入参数。

    5.3 startReg(env)

    /*static*/ int AndroidRuntime::startReg(JNIEnv* env)
    {
        ...
        // 调用register_jni_procs进行JNI注册
        if (register_jni_procs(gRegJNI, NELEM(gRegJNI), env) < 0) {
            env->PopLocalFrame(NULL);
            return -1;
        }
        env->PopLocalFrame(NULL);
    
        return 0;
    }
    
    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) {
                return -1;
            }
        }
        return 0;
    }
    
    static const RegJNIRec gRegJNI[] = {
        REG_JNI(register_com_android_internal_os_RuntimeInit),
        REG_JNI(register_android_os_SystemClock),
        REG_JNI(register_android_util_EventLog),
        REG_JNI(register_android_util_Log),
        REG_JNI(register_android_util_MemoryIntArray),
        ...
    };
    

    6. ZygoteInit.java

    上面appRuntime::start()启动虚拟机,通过jni调用ZygoteInit的main();ZygoteInit是c到java的入口,也是java的第一个进程,看一下main()的具体实现:

    // frameworks\base\core\java\com\android\internal\os
    public static void main(String argv[]) {
              ...
                boolean startSystemServer = false;
                String socketName = "zygote";
                String abiList = null;
                for (int i = 1; i < argv.length; i++) {
                    if ("start-system-server".equals(argv[i])) {
                        startSystemServer = true;   // 需要启动system server
                    } 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连接服务端
                registerZygoteSocket(socketName);
                Trace.traceBegin(Trace.TRACE_TAG_DALVIK, "ZygotePreload");
                
                // 预加载各类资源
                preload();
                ...
                // 由init.rc文件中配置的参数传递而来
                if (startSystemServer) {
                     // 开启系统服务
             startSystemServer(abiList, socketName);
                }
                // 进入循环等待ams通过socket通信来fork新的进程
                runSelectLoop(abiList);
                closeServerSocket();
        }
    

    main方法中主要做了:

    • 建立socket服务端
    • 启动各种系统服务如ams,wms,pms...
    • 进入死循环,等待和处理ams通过socket传递的请求。

    疑问点:既然android自身的binder能实现进程间通信,效率又高,为什么这里却选用socket,而不使用更好的binder,有什么限制吗?

    7.runSelectLoop(abiList);

    private static void runSelectLoop(String abiList) throws MethodAndArgsCaller {
            ArrayList<FileDescriptor> fds = new ArrayList<FileDescriptor>();
            ArrayList<ZygoteConnection> peers = new ArrayList<ZygoteConnection>();
    
            fds.add(sServerSocket.getFileDescriptor());
            peers.add(null); // 保持fds索引一致
    
            // 进入死循环,通过socket的accept会进入阻塞状态
            while (true) {
                StructPollfd[] pollFds = new StructPollfd[fds.size()];
                for (int i = 0; i < pollFds.length; ++i) {
                    pollFds[i] = new StructPollfd();
                    pollFds[i].fd = fds.get(i);
                    pollFds[i].events = (short) POLLIN;
                }
                try {
                    Os.poll(pollFds, -1);
                } catch (ErrnoException ex) {
                    throw new RuntimeException("poll failed", ex);
                }
                for (int i = pollFds.length - 1; i >= 0; --i) {
                    if ((pollFds[i].revents & POLLIN) == 0) {
                        continue;
                    }
                    if (i == 0) {
                        // == 0 时 获取请求,有的话加入list中,下一次循环走入else中进行任务执行
                        ZygoteConnection newPeer = acceptCommandPeer(abiList);
                        peers.add(newPeer);
                        fds.add(newPeer.getFileDesciptor());
                    } else {
                        // 处理请求
                        boolean done = peers.get(i).runOnce();
                        if (done) {
                            peers.remove(i);
                            fds.remove(i);
                        }
                    }
                }
            }
        }
    

    7.1 ZygoteConnection.runOnce()

    boolean runOnce() throws ZygoteInit.MethodAndArgsCaller {
      ...
      fd = ZygoteInit.getServerSocketFileDescriptor();
      pid = Zygote.forkAndSpecialize(parsedArgs.uid, parsedArgs.gid, parsedArgs.gids,...);
    
      if (pid == 0) {
         // 创建了新的进程,则运行程序本身的代码  pid>0表示父进程,<0表示fork失败
         handleChildProc(parsedArgs, descriptors, childPipeFd, newStderr);
         return true;
      } else {
          return handleParentProc(pid, descriptors, serverPipeFd, parsedArgs);
      }
    

    7.1.1 forkAndSpecialize()

    runOnce()方法中的Zygote.forkAndSpecialize()是fork出子进程的方法
    大致的步骤如下:

    • VM_HOOKS.preFork();调用dalvik_system_ZygoteHooks.cc源文件的preFork()做准备工作;
    • nativeForkAndSpecialize()本地方法,内部调用ForkAndSpecializeCommon(),这里才是linux的fork进程的具体实现,完成后再调用Zyogte的callPostForkChildHooks()回到java程序代码。
    • VM_HOOKS.postForkCommon();
    private static final ZygoteHooks VM_HOOKS = new ZygoteHooks();
    public static int forkAndSpecialize(int uid, int gid, int[] gids, int debugFlags,
              int[][] rlimits, int mountExternal, String seInfo, String niceName, int[] fdsToClose,
              String instructionSet, String appDataDir) {
            // VM_HOOKS 在libcore\dalvik\src\main\java\dalvik\system下
            // 对应的源文件在 art\runtime\native\dalvik_system_ZygoteHooks.cc
            VM_HOOKS.preFork();
            // native方法 具体实现在com_android_internal_os_zygote_nativeForkAndSpecialize
            int pid = nativeForkAndSpecialize(
                      uid, gid, gids, debugFlags, rlimits, mountExternal, seInfo, niceName, fdsToClose,
                      instructionSet, appDataDir);
            // Enable tracing as soon as possible for the child process.
            if (pid == 0) {
                Trace.setTracingEnabled(true);
    
                // Note that this event ends at the end of handleChildProc,
                Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "PostFork");
            }
            VM_HOOKS.postForkCommon();
            return pid;
        }
    
        private static void callPostForkChildHooks(int debugFlags, boolean isSystemServer,
                String instructionSet) {
            VM_HOOKS.postForkChild(debugFlags, isSystemServer, instructionSet);
        }
    

    7.2 handleChildProc()

    private void handleChildProc(Arguments parsedArgs,
      // 关闭子进程从Zygote fork过来的服务端socket
      closeSocket();
      ZygoteInit.closeServerSocket();
      ...
    
       if (parsedArgs.niceName != null) {   // 设置进程名称
          Process.setArgV0(parsedArgs.niceName);
       }
    
            if (parsedArgs.invokeWith != null) { // 没有传入--invoke-with,所以这里走的是else
                WrapperInit.execApplication(parsedArgs.invokeWith,
                        parsedArgs.niceName, parsedArgs.targetSdkVersion,
                        VMRuntime.getCurrentInstructionSet(),
                        pipeFd, parsedArgs.remainingArgs);
            } else {
                RuntimeInit.zygoteInit(parsedArgs.targetSdkVersion,
                        parsedArgs.remainingArgs, null /* classLoader */);
            }
        }
    

    代码最后几行的条件语句,通过参数的invoke-with来做判断,会走两个分支,两个分支的最终目的都是一样的,因为走到这里都是zygoteInitrunSelectLoop()走过来的,也就是我们开启的应用进程,不是startSystemServer,所以这里的分支最终目的是通过反射调用ActivityThreadmain方法,在虚拟机里的执行java程序代码。
    下面7.3和7.4分别来详细看一下上面的else和if分支,一般都会走到else中,所以先看一下。

    7.3 RuntimeInit.zygoteInit()

        public static final void zygoteInit(int targetSdkVersion, String[] argv, ClassLoader classLoader)
                throws ZygoteInit.MethodAndArgsCaller {
            if (DEBUG) Slog.d(TAG, "RuntimeInit: Starting application from zygote");
    
            Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "RuntimeInit");
            redirectLogStreams();
    
            commonInit();
            nativeZygoteInit();
            applicationInit(targetSdkVersion, argv, classLoader);
        }
    

    主要看流程不求甚解,commonInit就不看了,直接看nativeZygoteInit,这个本地方法对应AndroidRuntime类的com_android_internal_os_RuntimeInit_nativeZygoteInit,最终调用app_main.cppAppRuntime类的onZygoteInit()

    // frameworks\base\cmds\app_process\app_main.cpp
    class AppRuntime : public AndroidRuntime
    {
    public:
    virtual void onZygoteInit()
        {
            sp<ProcessState> proc = ProcessState::self();
            ALOGV("App process: starting thread pool.\n");
            proc->startThreadPool();
        }
    }
    

    startThreadPool主要是binder的一些操作

    String8 name = makeBinderThreadName();
    sp<Thread> t = new PoolThread(isMain);
    t->run(name.string());
    

    顺便理一下app_main.cpp中定义的类AppRuntimeAndroidRuntime的子类,
    AndroidRuntime.cpp路径是frameworks\base\core\jniAndroidRuntime.h路径
    frameworks\base\include\android_runtime
    接下来主要看applicationInit();

    7.3.1 applicationInit()

     private static void applicationInit(int targetSdkVersion, String[] argv, ClassLoader classLoader)
                throws ZygoteInit.MethodAndArgsCaller {
            nativeSetExitWithoutCleanup(true);
    
            // We want to be fairly aggressive about heap utilization, to avoid
            // holding on to a lot of memory that isn't needed.
            VMRuntime.getRuntime().setTargetHeapUtilization(0.75f);
            VMRuntime.getRuntime().setTargetSdkVersion(targetSdkVersion);
    
            final Arguments args;
            try {
                args = new Arguments(argv);
            } catch (IllegalArgumentException ex) {
                Slog.e(TAG, ex.getMessage());
                // let the process exit
                return;
            }
    
            // The end of of the RuntimeInit event (see #zygoteInit).
            Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
    
            // Remaining arguments are passed to the start class's static main
            // startClass: 如果AMS通过socket传递过来的是ActivityThread
            // 如果是SystemServer 则com.android.server.SystemServer
            invokeStaticMain(args.startClass, args.startArgs, classLoader);
        }
    
    private static void invokeStaticMain(String className, String[] argv, ClassLoader classLoader)
                throws ZygoteInit.MethodAndArgsCaller {
            ...
            cl = Class.forName(className, true, classLoader);
            m = cl.getMethod("main", new Class[] { String[].class });
            throw new ZygoteInit.MethodAndArgsCaller(m, argv);
        }
    

    applicationInit->invokeStaticMain->throw new ZygoteInit.MethodAndArgsCaller;
    可以看到通过抛个MethodAndArgsCaller异常来反射调用main();为什么抛异常方式去调用,其实应用程序出现异常时log,只有ZygoteInit.main
    ZygoteInit$MethodAndArgsCaller.run,而没有中间我们走过的这些过程,看起来程序就是从ZygoteInit.main开始的一样,可能是为了让日志看起来更清晰一点,省去了中间的很多无用log。但9.0这块又有变化可参考

    ...
    at java.lang.reflect.Method.invoke!(Native method)
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:738)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:628)
    

    7.4 WrapperInit.execApplication()

        public static void execApplication(String invokeWith, String niceName,
                int targetSdkVersion, String instructionSet, FileDescriptor pipeFd,
                String[] args) {
            StringBuilder command = new StringBuilder(invokeWith);
    
            final String appProcess;
            if (VMRuntime.is64BitInstructionSet(instructionSet)) {
                appProcess = "/system/bin/app_process64";
            } else {
                appProcess = "/system/bin/app_process32";
            }
            command.append(' ');
            command.append(appProcess);
    
            command.append(" /system/bin --application");
            if (niceName != null) {
                command.append(" '--nice-name=").append(niceName).append("'");
            }
            command.append(" com.android.internal.os.WrapperInit ");
            command.append(pipeFd != null ? pipeFd.getInt$() : 0);
            command.append(' ');
            command.append(targetSdkVersion);
            Zygote.appendQuotedShellArgs(command, args);
            Zygote.execShell(command.toString());
        }
    

    可以看出这种启动模式是通过拼接如同init.rc中启动server的字符串参数配置,最终调用Zygote.execShell(command.toString());会走到一开始的地方app_main::main(),只不过带了--application参数,回到app_main中来看

    int main(int argc, char* const argv[])
    {
    if (zygote) {
            runtime.start("com.android.internal.os.ZygoteInit", args, zygote);
        } else if (className) {
            // 走这里,之前介绍过这个start(),会执行RuntimeInit的main
            runtime.start("com.android.internal.os.RuntimeInit", args, zygote);
        } 
    }
    

    7.4.1 RuntimeInit.main()

        public static final void main(String[] argv) {
            enableDdms();
            if (argv.length == 2 && argv[1].equals("application")) {
                if (DEBUG) Slog.d(TAG, "RuntimeInit: Starting application");
                redirectLogStreams();
            } else {
                if (DEBUG) Slog.d(TAG, "RuntimeInit: Starting tool");
            }
    
            commonInit();
    
            /*
             * Now that we're running in interpreted code, call back into native code
             * to run the system.
             */
             // 该本地方法在AndroidRuntime中,会调用子类AppRuntime的onStart()(app_main.cpp中)
             // start()调用callMain,执行
            nativeFinishInit();
    
            if (DEBUG) Slog.d(TAG, "Leaving RuntimeInit!");
        }
    
    // AndroidRuntime.cpp
    static void com_android_internal_os_RuntimeInit_nativeFinishInit(JNIEnv* env, jobject clazz)
    {
        gCurRuntime->onStarted();
    }
    
      // 子类appRuntime的onStarted()
      virtual void onStarted()
        {
            sp<ProcessState> proc = ProcessState::self();
            ALOGV("App process: starting thread pool.\n");
            proc->startThreadPool();
    
            AndroidRuntime* ar = AndroidRuntime::getRuntime();
            ar->callMain(mClassName, mClass, mArgs);
    
            IPCThreadState::self()->stopProcess();
        }
    

    callMain的实现过程就是反射调用ActivityThreadmain();

    8. startSystemServer()

    private static boolean startSystemServer(String abiList, String socketName)
                throws MethodAndArgsCaller, RuntimeException {
    ...
            String args[] = {
                "--setuid=1000",
                "--setgid=1000",
                "--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,1021,1032,3001,3002,3003,3006,3007,3009,3010",
                "--capabilities=" + capabilities + "," + capabilities,
                "--nice-name=system_server",
                "--runtime-args",
                "com.android.server.SystemServer",
            };
    pid = Zygote.forkSystemServer(
                        parsedArgs.uid, parsedArgs.gid,
                        parsedArgs.gids,
                        parsedArgs.debugFlags,
                        null,
                        parsedArgs.permittedCapabilities,
                        parsedArgs.effectiveCapabilities);
    }
     if (pid == 0) { // 0表示子进程,大于0表示父进程,小于0表示fork失败
                if (hasSecondZygote(abiList)) {
                    waitForSecondaryZygote(socketName);
                }
    
                handleSystemServerProcess(parsedArgs);
            }
            // 方法结束,走到上面的runSelectLoop中
            return true;
    

    8.1 Zygote.forkSystemServer

        public static int forkSystemServer(int uid, int gid, int[] gids, int debugFlags,
                int[][] rlimits, long permittedCapabilities, long effectiveCapabilities) {
            VM_HOOKS.preFork();
            int pid = nativeForkSystemServer(
                    uid, gid, gids, debugFlags, rlimits, permittedCapabilities, effectiveCapabilities);
            // Enable tracing as soon as we enter the system_server.
            if (pid == 0) {
                Trace.setTracingEnabled(true);
            }
            VM_HOOKS.postForkCommon();
            return pid;
        }
    

    forkSystemServer->con_android_internal_os_Zygote.ForkAndSpecializeCommon()
    ForkAndSpecializeCommon中有调用了forkAndSpecialize()上面分析runSelectLoop()也走到这里,linux的fork前后操作不说了。

    8.2 handleSystemServerProcess()

     private static void handleSystemServerProcess(
                ZygoteConnection.Arguments parsedArgs)
                throws ZygoteInit.MethodAndArgsCaller {
            // system-server进程同样不需要想zygote进程那样需要socket。
            closeServerSocket();
    
           ...
            if (systemServerClasspath != null) {
                performSystemServerDexOpt(systemServerClasspath);
            }
    
            if (parsedArgs.invokeWith != null) {
                String[] args = parsedArgs.remainingArgs;
                if (systemServerClasspath != null) {
                    String[] amendedArgs = new String[args.length + 2];
                    amendedArgs[0] = "-cp";
                    amendedArgs[1] = systemServerClasspath;
                    System.arraycopy(parsedArgs.remainingArgs, 0, amendedArgs, 2, parsedArgs.remainingArgs.length);
                }
    
                WrapperInit.execApplication(parsedArgs.invokeWith,
                        parsedArgs.niceName, parsedArgs.targetSdkVersion,
                        VMRuntime.getCurrentInstructionSet(), null, args);
            } else {
                ClassLoader cl = null;
                if (systemServerClasspath != null) {
                    cl = createSystemServerClassLoader(systemServerClasspath,
                                                       parsedArgs.targetSdkVersion);
    
                    Thread.currentThread().setContextClassLoader(cl);
                }
                
                RuntimeInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs, cl);
            }
        }
    

    RuntimeInit.zygoteInit在上面也讲到过,重点是方法里面的applicationInit(targetSdkVersion, argv, classLoader);argv是第8节刚开始的那段代码里的,其中最后一个是com.android.server.SystemServer
    这里就反射调用了SystemServer的main方法;

    9.SystemServer.main()

    main方法中初始化一个SystemServer对象(它自己),并且调用了自己的run();

    private void run() {
      ...
      SystemProperties.set("persist.sys.dalvik.vm.lib.2", VMRuntime.getRuntime().vmLibrary());
      Looper.prepareMainLooper();  // loop对象
      // SystemServiceManager对象
      mSystemServiceManager = new SystemServiceManager(mSystemContext);
      LocalServices.addService(SystemServiceManager.class, mSystemServiceManager);
      ...
      startBootstrapServices(); // 优先级最高的最核心的一部分services 比如AMS
      startCoreServices();
      startOtherServices();
      Looper.loop(); // loop起来
    }
    

    9.1 startOtherServices()

    该方法也是启动一些service,代码超级长1000多行的方法,只看重点

    private void startOtherServices() {
      // 所有服务开启完成
      mActivityManagerService.systemReady(new Runnable() {
      })
    };
    

    所有系统服务开启完成后调用systemReady,判断activity栈中有没有对象,如果是null,开启第一个应用进程Launcher,然后就是startActivityForResult()->AMS通过socket通知Zygote进程fork,就是上面的runSelectLoop();关于AMS这块的Activity启动流程又是一个比较重要的流程。

    知识点:

    • Activity启动流程

    10. 总结

    一句话总结:init进程启动第一个java进程zygote,接着zygote fork出SystemServer进程并启动相关服务,服务启动完成启动Launcher应用进程。

    如果你刚刚才开始了解启动流程这部分内容,一定要有耐心一步一步去跟踪源码看下去,涉及到众多知识点,不懂可以先记录下来,以后逐个突破。Android启动的流程个人感觉是比较重要也是相对比较容易的一部分系统源码(流程容易,具体实现肯定不简单),启动的流程能够把很多知识点串联起来,搞清楚这块内容,为后面我们想进一步了解Android系统源码打下根基,清楚系统的大致轮廓。

    最后附上两张大神制作的类图和时序图
    Android启动流程类图.png Android启动流程时序图.png

    参考博客、书籍:
    Android启动篇 — init原理(二)
    Android启动流程简析
    图解Android - Zygote, System Server 启动分析
    邓凡平《深入理解Android Java虚拟机ART》
    林学森《深入理解Android内核设计思想》

    相关文章

      网友评论

        本文标题:ZygoteInit从c到java

        本文链接:https://www.haomeiwen.com/subject/qvjqsctx.html