【Android FrameWork (二) 】- Zygote


知识回顾

Android Framework 的第一个启动程序-init 主要工作流程:
1,挂载文件系统 创建文件目录 调用selinux_setup安全权限相关
2,初始化属性服务
3,开启属性服务 创建Epoll 注册监听(监听子进程一些情况 重启异常操作 对进程进行线程保护)
4,LoadBootScripts 加载 init.rc文件 进行解析 调用do_class_service
5,start::service fork我们子进程 启动子进程Zygote

前言

通过知识回顾我们了解到 Zygote是init的子进程,Zygote是一个孵化器,system_server和所有的应用程序都是由他创建出来的。最初的时候Zygote进程的名称并不是Zygote而是app_process,Zygote启动后,Linux系统下的pctrl系统会调用app_process,所以把名称换成了Zygote。

Zygote他是一个C/S架构。Zygote进程作为服务端,通过Socket的方式和其他进程进行通信。
当接收到数据的时候会fork子进程,fork是不会复制父进程的内存,而是和父进程共享一个内存空间,只有需要进行内存数据修改的时候才会进行内存复制,也就是常说的读时共享,写时复制。


源码分析

1.Zygote的启动

通过知识回顾我们知道在init中我们对init.rc进行解析 并启动相应service 遍历serviceList 调用start函数 fork进程

#解析服务 并且添加到serviceList中
service zygote /system/bin/app_process64 -Xzygote /system/bin --zygote --start-system-server
    class main
    priority -20
    user root
    group root readproc reserved_disk
    socket zygote stream 660 root system
    socket usap_pool_primary 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
    
#遍历serviceList 调用start函数 fork进程 execv执行app_process64
on nonencrypted class_start main class_start late_start
    

2.app_main.cpp

1,创建AppRuntime extents AndroidRunTime 将参数传递给AppRuntime并初始化
2,接着根据init传递过来的参数–zygote 把zygote 设置成true表示是以zygote模式启动
(如果需要开启system_server的会把start-system-server 也设置为true;如果传递的是application就是以app模式启动,他就会查找对应的className;如果className不为空就会添加对应的参数,否则就是Zygote模式;
3,在Zygote模式中会先创建Davik的缓存目录。最后调用runtime.start(),看是以什么模式启动,如果是Zygote模式启动就会传递com.android.internal.os.ZygoteInit和将整理的参数以及zygote 传递下去,如果是app模式就会传递com.android.internal.os.RuntimeInit和 args以及 zygote;

//init传递过来的参数如下 -Xzygote /system/bin --zygote --start-system-server
int main(int argc, char* const argv[])
{
    //#ifndef LOG_NDEBUG
    //#ifdef NDEBUG
    //#define LOG_NDEBUG 1
    //#else
    //#define LOG_NDEBUG 0  所以这里是true 会把参数存放到argv_String中,然后打印出来
    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,并将参数传递给AppRuntime
    AppRuntime runtime(argv[0], computeArgBlockSize(argc, argv));
    argc--;
    argv++;
    bool known_command = false;

    int i;
    for (i = 0; i < argc; i++) {
        if (known_command == true) {
          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) {
          if (strcmp(argv[i], spaced_commands[j]) == 0) {
            known_command = true;
            ALOGV("app_process main found known command '%s'", argv[i]);
          }
        }

        if (argv[i][0] != '-') {//如果参数第一个字符是'-'跳出循环,Zygote传递的第一个参数是-Xzygote 所以执行到这里会跳出循环
            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]);
    }

    // Parse runtime arguments.  Stop at first unrecognized option.
    bool zygote = false;
    bool startSystemServer = false;
    bool application = false;
    String8 niceName;
    String8 className;

    ++i;  
    while (i < argc) {
        const char* arg = argv[i++];
        if (strcmp(arg, "--zygote") == 0) {//传递的参数有--zygote的就把zygote赋值为true niceName = zygote
            zygote = true;
            niceName = ZYGOTE_NICE_NAME;
        } else if (strcmp(arg, "--start-system-server") == 0) { //传递的参数有start--system-server 把startSystemServer 赋值为tue表示当前进程的main是需要开启system_server的
            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) {//application程序传递过来的className 也就是需要启动的class
            className.setTo(arg);
            break;
        } else {
            --i;
            break;
        }
    }

    Vector<String8> args;
    if (!className.isEmpty()) {//如果class不为空 说明是application,但是此时我们是空的,所以我们会走下面的分支
        args.add(application ? String8("application") : String8("tool"));
        runtime.setClassNameAndArgs(className, argc - i, argv + i);

        if (!LOG_NDEBUG) {
          String8 restOfArgs;
          char* const* argv_new = argv + i;
          int argc_new = argc - i;
          for (int k = 0; k < argc_new; ++k) {
            restOfArgs.append(""");
            restOfArgs.append(argv_new[k]);
            restOfArgs.append("" ");
          }
          ALOGV("Class name = %s, args = %s", className.string(), restOfArgs.string());
        }
    } else {//这里就是zygote启动模式
        // We're in zygote mode.
        maybeCreateDalvikCache();//创建Dalvik的缓存目录, data/dalvik-cache的目录

        if (startSystemServer) {//如果需要运行system_server的 会添加这个参数
            args.add(String8("start-system-server"));
        }

        char prop[PROP_VALUE_MAX];
        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=");
        abiFlag.append(prop);
        args.add(abiFlag);

        for (; i < argc; ++i) {
            args.add(String8(argv[i]));
        }
    }

    if (!niceName.isEmpty()) {//设置进程别名
        runtime.setArgv0(niceName.string(), true /* setProcName */);
    }

    if (zygote) {//注意这里之前传递的参数zygote 所以这里是true。他会调用runtime的start函数 传递com.android.internal.os.ZygoteInit 以及 init传递过来的参数 和true
        runtime.start("com.android.internal.os.ZygoteInit", args, zygote);
    } else if (className) {//application模式
        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.");
    }
}

3.AppRuntime

校验一些目录,然后加载libart.so,调用startVm创建VM虚拟机,创建成功之后会调用onVmCreated(env)回到AppRuntime中,startReg()注册函数 开启注册多种jni函数,不过我们当前是Zygote 直接 return。

void AndroidRuntime::start(const char* className, const Vector<String8>& 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)));
        }
    }

    //获取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);
    }
    //获取ANDROID_RUNTIME_ROOT目录
    const char* runtimeRootDir = getenv("ANDROID_RUNTIME_ROOT");
    if (runtimeRootDir == NULL) {
        LOG_FATAL("No runtime directory specified with ANDROID_RUNTIME_ROOT environment variable.");
        return;
    }

    const char* tzdataRootDir = getenv("ANDROID_TZDATA_ROOT");
    if (tzdataRootDir == NULL) {
        LOG_FATAL("No tz data directory specified with ANDROID_TZDATA_ROOT environment variable.");
        return;
    }

    /* 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);//当VM创建成功后会把env传递给AppRuntime来进行处理。


    if (startReg(env) < 0) {//开启注册函数 会注册很多关键的JNI函数 比如com/android/internal/os/ZygoteInit.nativeZygoteInit->com_android_internal_os_ZygoteInit_nativeZygoteInit等等函数的注册
        ALOGE("Unable to register all android natives\n");
        return;
    }

    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);
    //创建对应的class 此时的className 就是main函数传递过来的com.android.internal.os.ZygoteInit 把他存入strArray
    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);
    }

    char* slashClassName = toSlashClassName(className != NULL ? className : "");//把className的. 替换成/
    jclass startClass = env->FindClass(slashClassName);
    if (startClass == NULL) {
        ALOGE("JavaVM unable to locate class '%s'\n", slashClassName);
        /* keep going */
    } else {
        //执行ZygoteInit的main方法 带着传递过来的参数 回调到java层
        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 {
            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");
}

4.ZygoteInit.java

创建ZygoteServer --> 调用了preload() 预加载资源文件(Fragment Activity Drawable 等)–> gcAndFinalize()


public static void main(String argv[]) {
    
    //zygoteServer服务端
    ZygoteServer zygoteServer = null;

    ZygoteHooks.startZygoteNoThreadCreation();

    try {
        Os.setpgid(0, 0);
    } catch (ErrnoException ex) {
        throw new RuntimeException("Failed to setpgid(0,0)", ex);
    }

    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 zygoteSocketName = "zygote";
        String abiList = null;
        boolean enableLazyPreload = false;
        for (int i = 1; i < argv.length; i++) {
            if ("start-system-server".equals(argv[i])) {//此时我们传递的是有值的 所以会把startSystemServer 设置为true
                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)) {
                zygoteSocketName = 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.resetNicePriority();
        }

        bootTimingsTraceLog.traceBegin("PostZygoteInitGC");
        gcAndFinalize();//GC的初始化并启动
        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.initNativeState(isPrimaryZygote);

        ZygoteHooks.stopZygoteNoThreadCreation();

        zygoteServer = new ZygoteServer(isPrimaryZygote);

        if (startSystemServer) {//此时为True 调用forkSystemServer
            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.
        //服务端开启循环 等待客户端来请求
        caller = zygoteServer.runSelectLoop(abiList);
    } catch (Throwable ex) {
        Log.e(TAG, "System zygote died with exception", ex);
        throw ex;
    } finally {
        if (zygoteServer != null) {
            zygoteServer.closeServerSocket();
        }
    }

    // We're in the child process and have exited the select loop. Proceed to execute the
    // command.
    if (caller != null) {
        caller.run();
    }
}

##4.SystemServer
startSystemServer 为 True 会执行 forkSystemServer–>执行zygoteServer.runSelectLoop(); 调用runSelectLoop();函数进入等待状态,等待客户端的连接.

Runnable runSelectLoop(String abiList) {
    ArrayList<FileDescriptor> socketFDs = new ArrayList<FileDescriptor>();
    ArrayList<ZygoteConnection> peers = new ArrayList<ZygoteConnection>();

    socketFDs.add(mZygoteSocket.getFileDescriptor());
    peers.add(null);

    while (true) {
        fetchUsapPoolPolicyPropsWithMinInterval();

        int[] usapPipeFDs = null;
        StructPollfd[] pollFDs = null;//需要监听的fds

        if (mUsapPoolEnabled) {
            usapPipeFDs = Zygote.getUsapPipeFDs();
            pollFDs = new StructPollfd[socketFDs.size() + 1 + usapPipeFDs.length];
        } else {
            pollFDs = new StructPollfd[socketFDs.size()];
        }


        int pollIndex = 0;
        for (FileDescriptor socketFD : socketFDs) {
            pollFDs[pollIndex] = new StructPollfd();
            pollFDs[pollIndex].fd = socketFD;
            pollFDs[pollIndex].events = (short) POLLIN;//对每一个socket需要关注POLLIN
            ++pollIndex;
        }

        final int usapPoolEventFDIndex = pollIndex;

        if (mUsapPoolEnabled) {
            pollFDs[pollIndex] = new StructPollfd();
            pollFDs[pollIndex].fd = mUsapPoolEventFD;
            pollFDs[pollIndex].events = (short) POLLIN;
            ++pollIndex;

            for (int usapPipeFD : usapPipeFDs) {
                FileDescriptor managedFd = new FileDescriptor();
                managedFd.setInt$(usapPipeFD);

                pollFDs[pollIndex] = new StructPollfd();
                pollFDs[pollIndex].fd = managedFd;
                pollFDs[pollIndex].events = (short) POLLIN;
                ++pollIndex;
            }
        }

        try {//zygote阻塞在这里等待poll事件
            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;
            }

            if (pollIndex == 0) {//初始化的时候socketFDs中只有server socket。所以会创建新的通信连接调用acceptCommandPeer
                // Zygote server socket

                ZygoteConnection newPeer = acceptCommandPeer(abiList);
                peers.add(newPeer);
                socketFDs.add(newPeer.getFileDescriptor());

            } else if (pollIndex < usapPoolEventFDIndex) {
                // Session socket accepted from the Zygote server socket

                try {//获取到客户端链接
                    ZygoteConnection connection = peers.get(pollIndex);
                    //客户端有请求进行处理
                    final Runnable command = connection.processOneCommand(this);

                    if (mIsForkChild) {
                        if (command == null) {
                            throw new IllegalStateException("command == null");
                        }

                        return command;
                    } else {
                        if (command != null) {
                            throw new IllegalStateException("command != null");
                        }

                        // We don't know whether the remote side of the socket was closed or
                        // not until we attempt to read from it from processOneCommand. This
                        // shows up as a regular POLLIN event in our regular processing loop.
                        if (connection.isClosedByPeer()) {
                            connection.closeSocket();
                            peers.remove(pollIndex);
                            socketFDs.remove(pollIndex);
                        }
                    }
                } catch (Exception e) {
                    if (!mIsForkChild) {

                        Slog.e(TAG, "Exception executing zygote command: ", e);

                        ZygoteConnection conn = peers.remove(pollIndex);
                        conn.closeSocket();

                        socketFDs.remove(pollIndex);
                    } else {
                        Log.e(TAG, "Caught post-fork exception in child process.", e);
                        throw e;
                    }
                } finally {
                    mIsForkChild = false;
                }
            } else {
                long messagePayload = -1;

                try {
                    byte[] buffer = new byte[Zygote.USAP_MANAGEMENT_MESSAGE_BYTES];
                    int readBytes = Os.read(pollFDs[pollIndex].fd, buffer, 0, buffer.length);

                    if (readBytes == Zygote.USAP_MANAGEMENT_MESSAGE_BYTES) {
                        DataInputStream inputStream =
                                new DataInputStream(new ByteArrayInputStream(buffer));

                        messagePayload = inputStream.readLong();
                    } else {
                        Log.e(TAG, "Incomplete read from USAP management FD of size "
                                + readBytes);
                        continue;
                    }
                } catch (Exception ex) {
                    if (pollIndex == usapPoolEventFDIndex) {
                        Log.e(TAG, "Failed to read from USAP pool event FD: "
                                + ex.getMessage());
                    } else {
                        Log.e(TAG, "Failed to read from USAP reporting pipe: "
                                + ex.getMessage());
                    }

                    continue;
                }

                if (pollIndex > usapPoolEventFDIndex) {
                    Zygote.removeUsapTableEntry((int) messagePayload);
                }

                usapPoolFDRead = true;
            }
        }

        if (usapPoolFDRead) {
            int[] sessionSocketRawFDs =
                    socketFDs.subList(1, socketFDs.size())
                            .stream()
                            .mapToInt(fd -> fd.getInt$())
                            .toArray();

            final Runnable command = fillUsapPool(sessionSocketRawFDs);

            if (command != null) {
                return command;
            }
        }
    }
}

拓展知识

为什么在zygote中进行预加载资源呢?

Zygote 会fork我们的应用进程 而我们的fork的原理:读时共享 写时复制的机制来进行内存共享 所以在这里进行预加载 所孵化的应用也默认拥有这些资源
Fork出来的子进程是共享的

System.gc & Runtime.gc区别?

System.gc :java层函数 无法保证gc回收期调用,回收不一定立马执行,具体执行需要看虚拟机
Runtime.gc:native层函数

为什么预加载Class的时候要使用Class.forname呢?Class.forname和loadClass有什么区别?

Class.forName除了把class加载到jvm中,还会对class进行解释,并且执行类中的static块。而loadClass只是把class加载到jvm中,只有在newinstance中才会执行static。

Zygote是通过什么进行通信的?

通过socket进行通信并没有通过binder,因为这个过程binder还没有建立,只有在创建ProcessState之后才可以使用Binder。

简述Zygote的流程

1.startVm函数创建虚拟机并调用startReg函数注册JNI环境。唤起zygoteInit.main
2.forkSystemServer。
3.preload()预加载class 系统资源。
4.调用runSelectLoop()函数 循环等待客户端的连接。
5.有客户端的连接后调用processOneCommand()函数 fork进程,初始化进程,创建ProcessState初始化binder。
6.根据请求的targetClass 执行Main函数。

总结

1,Zygote的启动是init在解析init.rc文件时候fork出来的进程;
2,在app_main.cpp文件的main函数中创建AppRuntime,判断是Zygote还是应用程序
3,调用runtime.start (com.android.internal.os.zygoteinit)AndroidRuntime_AppRuntime.cpp中
4,AndroidRunTime::startstart中调用startVM(env) 创建java虚拟机,调用StartReg(env)注册JNI函数,通过jni调用唤起zygoteInit.main
5,在zygoteInit.main中forkSystemServer 创建systemserver,调用 preload 预加载资源文件 包括activity fragment drawable 等,然后调用runSelectLoop();函数进入等待状态,等待客户端的连接.
6,ZygoteServer的runSelectLoop是一个死循环,在循环中Zygote等到poll事件的到来,如果有客户端连接进来会调用ZygoteConnect的processOneCommand()
7,ZygoteConnect的processOneCommand()会先通过调用com_android_internal_os_Zygote.cpp的native函数com_android_internal_os_Zygote_nativeForkAndSpecializefork出来对应的进程,fork出来后会关闭ServerSocket,因为子进程是Zygote孵化出来的,所以子进程fork出来后第一件事就是关闭掉socket。fork进程完毕之后调用HandleChildProc来设置子进程相关的信息,如果!isZygote会调用ZygoteInit.zygoteInit(parsedArgs.mTargetSdkVersion, parsedArgs.mRemainingArgs, null)返回到ZygoteInit执行zygoteInit()函数。
在Zygoteconnection.java中
8, native层。forkAndSpecialize fork子进程
9,handleChildProc 处理子进程 关闭socket
10,ProcessState 进程信息
创建进程信息 开启线程池 打开binder
11,RuntimeInit.applicaitonInit 对函数进行包装 然后进行一个返回
12,调用main函数
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值