美文网首页Android
Zygote底层启动流程简单分析

Zygote底层启动流程简单分析

作者: Spirituality韬 | 来源:发表于2018-04-28 16:38 被阅读0次

    Zygote的启动

    Android大部分应用程序和系统进程都是通过Zygote来生成的
    源码下
    /system/core/rootdir/init.rc

    import /init.${ro.zygote}.rc     #根据32和64位机器区分
    

    其中对init.zygote32.rc分析

    service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server
        class main
        priority -20
        user root
        group root readproc
        socket zygote stream 660 root system
        onrestart write /sys/android_power/request_state wake
        ...
       writepid /dev/cpuset/foreground/tasks
    

    从zygote的path可以看出,他所在的程序名叫“app_process”,对整个Android源码搜索找到/frameworks/base/cmds/app_process这个目录下,该目录下的app_main.cpp中main函数可以,通过init.zygote32.rc传递的参数来启动

      ...... --zygote --start-system-server
    if (zygote) {
        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.");
    }
    

    app_process将启动"ZygoteInit"并且启动system server。runtime实际是一个AndroidRuntime对象,其start在源码/frameworks/base/core/jni/AndroidRuntime.cpp文件中

    if (startVm(&mJavaVM, &env, zygote) != 0) {
        return;
    }
    onVmCreated(env);
    

    这条语句启动Java虚拟机,启动成功在进入/frameworks/base/core/java/com/android/internal/os/ZygoteInit.java中执行。

    ZygoteInit.java

    public static void main(String argv[]) {
        ...
        //通过上面传进来的参数来设置执行逻辑
        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]);
                }
            }
        //注册zygote服务端Socket对象
        zygoteServer.registerServerSocket(socketName);
        if (!enableLazyPreload) {
              preload(bootTimingsTraceLog);
         }
         ...
        if (startSystemServer) {
            startSystemServer(abiList, socketName, zygoteServer);
        }
        Log.i(TAG, "Accepting command socket connections");
        //
        zygoteServer.runSelectLoop(abiList);
        zygoteServer.closeServerSocket();
        ...
     }
    

    通过main函数可以知道 ZygoteInit利用ZygoteServer为zygote命令连接注册一个服务器套接字,一旦一个程序需要运行时,系统会通过这个Socket在第一时间通知“总管家”,并由它负责实际的进程孵化过程。
    从传递的参数来看这些都是执行得
    1.预加载虚拟机运行时所需要的各类资源preload(bootTimingsTraceLog);
    2.利用UNIX的fork机制SystemServer(下章),从代码上看新建一个专门的进程来承载系统服务的运行。
    3.zygoteServer.runSelectLoop这是一个死循环(Socket通信中不陌生),作为zygote的守护主体。
    ZygoteServer.java

     void runSelectLoop(String abiList) throws Zygote.MethodAndArgsCaller {
        ArrayList<FileDescriptor> fds = new ArrayList<FileDescriptor>();
        ArrayList<ZygoteConnection> peers = new ArrayList<ZygoteConnection>();
    
        fds.add(mServerSocket.getFileDescriptor());
        peers.add(null);
    
        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) {
                    ZygoteConnection newPeer = acceptCommandPeer(abiList);
                    peers.add(newPeer);
                    fds.add(newPeer.getFileDesciptor());
                } else {
                    boolean done = peers.get(i).runOnce(this);
                    if (done) {
                        peers.remove(i);
                        fds.remove(i);
                    }
                }
            }
        }
    }
    

    相关文章

      网友评论

        本文标题:Zygote底层启动流程简单分析

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