Zygote进程启动分析

最近在追溯Activity启动的流程,顺手温习下Android上层的启动流程,就从Zygote进程启动开始。

Zygote进程是由linux的init进程启动的,是所有android进程的父进程,包括systemserver和所有的应用进程都是由Zygote fork出来。

Init进程在启动Zygote进程时,会调用ZygoteInit.main方法(MTK平台项目代码,其中残留了一些mtk修改的痕迹)

    public static void main(String argv[]) {
        /// M: GMO Zygote64 on demand @{
        DEBUG_ZYGOTE_ON_DEMAND =
            SystemProperties.get(PROP_ZYGOTE_ON_DEMAND_DEBUG).equals("1");
        if (DEBUG_ZYGOTE_ON_DEMAND) {
            Log.d(TAG, "ZygoteOnDemand: Zygote ready = " + sZygoteReady);
        }
        String socketName = "zygote";
        /// M: GMO Zygote64 on demand @}

        // Mark zygote start. This ensures that thread creation will throw
        // an error.
        ZygoteHooks.startZygoteNoThreadCreation();

        try {
            Trace.traceBegin(Trace.TRACE_TAG_DALVIK, "ZygoteInit");
            RuntimeInit.enableDdms();
            /// M: Added for BOOTPROF
            //MTPROF_DISABLE = "1".equals(SystemProperties.get("ro.mtprof.disable"));
            // Start profiling the zygote initialization.
            SamplingProfilerIntegration.start();

            boolean startSystemServer = false;
            String abiList = null;
            for (int i = 1; i < argv.length; i++) {
                if ("start-system-server".equals(argv[i])) {
                    startSystemServer = 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.");
            }

            registerZygoteSocket(socketName);
            Trace.traceBegin(Trace.TRACE_TAG_DALVIK, "ZygotePreload");
            EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_START,
                SystemClock.uptimeMillis());
            /// M: Added for BOOTPROF
            addBootEvent("Zygote:Preload Start");

            /// M: GMO Zygote64 on demand @{
            /// M: Added for Zygote preload control @{
            preloadByName(socketName);
            /// @}
            /// M: GMO Zygote64 on demand @}

            EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_END,
                SystemClock.uptimeMillis());
            Trace.traceEnd(Trace.TRACE_TAG_DALVIK);

            // Finish profiling the zygote initialization.
            SamplingProfilerIntegration.writeZygoteSnapshot();

            // Do an initial gc to clean up after startup
            Trace.traceBegin(Trace.TRACE_TAG_DALVIK, "PostZygoteInitGC");
            gcAndFinalize();
            Trace.traceEnd(Trace.TRACE_TAG_DALVIK);

            Trace.traceEnd(Trace.TRACE_TAG_DALVIK);

            // Disable tracing so that forked processes do not inherit stale tracing tags from
            // Zygote.
            Trace.setTracingEnabled(false);

            // Zygote process unmounts root storage spaces.
            Zygote.nativeUnmountStorageOnInit();

            /// M: Added for BOOTPROF
            addBootEvent("Zygote:Preload End");

            ZygoteHooks.stopZygoteNoThreadCreation();

            /// N: Move MPlugin init after preloading due to "Zygote: No Thread Creation Issues". @{
            boolean preloadMPlugin = false;
            if (!sZygoteOnDemandEnabled) {
                preloadMPlugin = true;
            } else {
                if ("zygote".equals(socketName)) {
                    preloadMPlugin = true;
                }
            }
            if (preloadMPlugin) {
                Log.i(TAG1, "preloadMappingTable() -- start ");
                PluginLoader.preloadPluginInfo();
                Log.i(TAG1, "preloadMappingTable() -- end ");
            }
            /// @}

            if (startSystemServer) {
                startSystemServer(abiList, socketName);
            }

            /// M: GMO Zygote64 on demand @{
            sZygoteReady = true;
            if (DEBUG_ZYGOTE_ON_DEMAND) {
                Log.d(TAG, "ZygoteOnDemand: Zygote ready = " + sZygoteReady +
                    ", socket name: " + socketName);
            }
            /// M: GMO Zygote64 on demand @}

            Log.i(TAG, "Accepting command socket connections");
            runSelectLoop(abiList);

            /// M: GMO Zygote64 on demand @{
            zygoteStopping("ZygoteOnDemand: End of runSelectLoop", socketName);
            /// M: GMO Zygote64 on demand @}

            closeServerSocket();
        } catch (MethodAndArgsCaller caller) {
            caller.run();
        } catch (RuntimeException ex) {
            Log.e(TAG, "Zygote died with exception", ex);
            closeServerSocket();
            throw ex;
        }

        /// M: GMO Zygote64 on demand @{
        zygoteStopping("ZygoteOnDemand: End of main function", socketName);
        /// M: GMO Zygote64 on demand @}
    }

1. Mark zygote start.

 // Mark zygote start. This ensures that thread creation will throw
 // an error.
ZygoteHooks.startZygoteNoThreadCreation();    

标记zygote启动开始,调用ZygoteHooks的Jni方法,原因不是特别理解,贴出该方法google给的说明:
/**
* Called by the zygote when starting up. It marks the point when any thread
* start should be an error, as only internal daemon threads are allowed there.
*/
public static native void startZygoteNoThreadCreation();
zygote启动时调用,在这里启动任意其他线程都是错误的,只有内部的守护线程被允许。

2. ddms服务

RuntimeInit.enableDdms();

3.启动系能统计

SamplingProfilerIntegration.start();

4.解析参数列表

            boolean startSystemServer = false;
            String abiList = null;
            for (int i = 1; i < argv.length; i++) {
                if ("start-system-server".equals(argv[i])) {
                    startSystemServer = 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]);
                }
            }

判断systemserver是否启动,获取socketname等等

5.注册Socket

registerZygoteSocket(socketName);

    private static void registerZygoteSocket(String socketName) {
        if (sServerSocket == null) {
            int fileDesc;
            final String fullSocketName = ANDROID_SOCKET_PREFIX + socketName;
            try {
                String env = System.getenv(fullSocketName);
                fileDesc = Integer.parseInt(env);
            } catch (RuntimeException ex) {
                throw new RuntimeException(fullSocketName + " unset or invalid", ex);
            }

            try {
                FileDescriptor fd = new FileDescriptor();
                fd.setInt$(fileDesc);
                sServerSocket = new LocalServerSocket(fd);
            } catch (IOException ex) {
                throw new RuntimeException(
                        "Error binding to local socket '" + fileDesc + "'", ex);
            }
        }
    }

初始化Server端(也就是Zygote)的socket。值得一提的是,这里用到的socket类型是LocalSocket, 它是Android对Linux 的 Local Socket的一个封装。Local Socket 是Linux提供的一种基于Socket的进程间通信方式,对Server端来讲,唯一的区别就是bind到一个本地的文件描述符(fd)而不是某个IP地址和端口号。

6.预加载资源

static void preload() {
    Log.d(TAG, "begin preload");
    Trace.traceBegin(Trace.TRACE_TAG_DALVIK, "BeginIcuCachePinning");
    beginIcuCachePinning();
    Trace.traceEnd(Trace.TRACE_TAG_DALVIK);
    Trace.traceBegin(Trace.TRACE_TAG_DALVIK, "PreloadClasses");
    preloadClasses();         //预加载位于/system/etc/preloaded-classes文件中的类
    Trace.traceEnd(Trace.TRACE_TAG_DALVIK);
    Trace.traceBegin(Trace.TRACE_TAG_DALVIK, "PreloadResources");
    preloadResources();    //预加载资源,包含drawable和color资源
    Trace.traceEnd(Trace.TRACE_TAG_DALVIK);
    Trace.traceBegin(Trace.TRACE_TAG_DALVIK, "PreloadOpenGL");
    preloadOpenGL();    //预加载OpenGL
    Trace.traceEnd(Trace.TRACE_TAG_DALVIK);
    preloadSharedLibraries();     //通过System.loadLibrary()方法,
                                //预加载"android","compiler_rt","jnigraphics"这3个共享库
    preloadTextResources();      //预加载  文本连接符资源
    // Ask the WebViewFactory to do any initialization that must run in the zygote process,
    // for memory sharing purposes.
    WebViewFactory.prepareWebViewInZygote();   //仅用于zygote进程,用于内存共享的进程
    endIcuCachePinning();
    warmUpJcaProviders();
    Log.d(TAG, "end preload");
}

对于类加载,采用反射机制Class.forName()方法来加载。对于资源加载,主要是 com.android.internal.R.array.preloaded_drawables和com.android.internal.R.array.preloaded_color_state_lists,在应用程序中以com.android.internal.R.xxx开头的资源,便是此时由Zygote加载到内存的。

zygote进程内加载了preload()方法中的所有资源,当需要fork新进程时,采用copy on write技术,如下:

Zygote进程启动分析_第1张图片

7.gc操作

    /**
     * Runs several special GCs to try to clean up a few generations of
     * softly- and final-reachable objects, along with any other garbage.
     * This is only useful just before a fork().
     */
    /*package*/ static void gcAndFinalize() {
        final VMRuntime runtime = VMRuntime.getRuntime();

        /* runFinalizationSync() lets finalizers be called in Zygote,
         * which doesn't have a HeapWorker thread.
         */
        System.gc();
        runtime.runFinalizationSync();
        System.gc();
    }

Runs多次gc,保证清理?

8.startSystemServer

    private static boolean startSystemServer(String abiList, String socketName)
            throws MethodAndArgsCaller, RuntimeException {
        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_RESOURCE,
            OsConstants.CAP_SYS_TIME,
            OsConstants.CAP_SYS_TTY_CONFIG
        );
        /* 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",
            /// M: ANR mechanism for system_server add shell(2000) group to access
            ///    /sys/kernel/debug/tracing/tracing_on
            "--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,1021,1032,2000," +
                "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子进程,用于运行system_server
            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 */
    //进入子进程system_server
        if (pid == 0) {
            if (hasSecondZygote(abiList)) {
                waitForSecondaryZygote(socketName);
            }
        // 完成system_server进程剩余的工作
            handleSystemServerProcess(parsedArgs);
        }

        return true;
    }

9.runSelectLoop

    /**
     * Runs the zygote process's select loop. Accepts new connections as
     * they happen, and reads commands from connections one spawn-request's
     * worth at a time.
     *
     * @throws MethodAndArgsCaller in a child process when a main() should
     * be executed.
     */
    private static void runSelectLoop(String abiList) throws MethodAndArgsCaller {
        ArrayList fds = new ArrayList();
        ArrayList peers = new ArrayList();
    //sServerSocket是socket通信中的服务端,即zygote进程
        fds.add(sServerSocket.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);
            }
//采用I/O多路复用机制,当客户端发出连接请求或者数据处理请求时,跳过continue,执行后面的代码
            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();
                    if (done) {
                        peers.remove(i);
                        fds.remove(i);
                    }
                }
            }
        }
    }

Zygote采用高效的I/O多路复用机制,保证在没有客户端连接请求或数据处理时休眠,否则响应客户端的请求。

10.简单小结

ZygoteInit.main方法是android java代码开始的地方,

  • registerZygoteSocket()建立socket通道,zygote作为通信的服务端,用于响应客户端请求;
  • preload()预加载通用类、drawable和color资源、openGL以及共享库以及WebView,用于提高ap启动效率;
  • zygote完毕大部分工作,接下来再通过startSystemServer(),fork得力帮手system_server进程,也是上层framework的运行载体。
  • zygote功成身退,调用runSelectLoop(),随时待命,当接收到请求创建新进程请求时立即唤醒并执行相应工作。

参考链接:
http://www.cnblogs.com/samchen2009/p/3294713.html
http://gityuan.com/2016/02/14/android-system-server/
http://blog.csdn.net/omnispace/article/details/51773292

你可能感兴趣的:(Zygote进程启动分析)