美文网首页
Android源码分析--Zygote进程启动流程

Android源码分析--Zygote进程启动流程

作者: forty_seven | 来源:发表于2017-04-18 17:42 被阅读94次

    Android系统的Zygote进程是所有的android进程的父进程,包括SystemServer和各种应用进程都是通过Zygote进程fork出来的。而Zygote进程则是通过Linux系统的init进程启动的;

    android系统中各种进程的启动方式:
    init进程 –> Zygote进程 –> SystemServer进程 –>各种应用进程

    • init进程:linux的根进程;android系统是基于linux系统的,因此可以算作是整个android操作系统的第一个进程;
    • Zygote进程:android系统的根进程;主要作用:fork出SystemServer进程和各种应用进程;
    • SystemService进程:主要是在这个进程中启动系统的各项服务,比如ActivityManagerService,PackageManagerService,WindowManagerService服务等等;
    • 各种应用进程:启动自己编写的客户端应用时,一般都是重新启动一个应用进程,有自己的虚拟机与运行环境;

    本文主要介绍一下Zygote进程的启动流程,关于SystenServer进程和各种应用进程的启动方式会在以后的文章中介绍。

    1. Zygote类的main方法

    init进程在启动Zygote进程时一般都会调用ZygoteInit类的main方法,因此我们这里看一下该方法的具体实现(基于android23源码);

    public static void main(String argv[]) {
            try {
                RuntimeInit.enableDdms();
                // Start profiling the zygote initialization.
                SamplingProfilerIntegration.start();
    
                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;
                    } 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);
                EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_START,
                    SystemClock.uptimeMillis());
                preload();
                EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_END,
                    SystemClock.uptimeMillis());
    
                // Finish profiling the zygote initialization.
                SamplingProfilerIntegration.writeZygoteSnapshot();
    
                // Do an initial gc to clean up after startup
                gcAndFinalize();
    
                // Disable tracing so that forked processes do not inherit stale tracing tags from
                // Zygote.
                Trace.setTracingEnabled(false);
    
                if (startSystemServer) {
                    startSystemServer(abiList, socketName);
                }
    
                Log.i(TAG, "Accepting command socket connections");
                runSelectLoop(abiList);
    
                closeServerSocket();
            } catch (MethodAndArgsCaller caller) {
                caller.run();
            } catch (RuntimeException ex) {
                Log.e(TAG, "Zygote died with exception", ex);
                closeServerSocket();
                throw ex;
            }
        }
    
    • 第一行是调用enableDdms(),设置DDMS可用;可以发现DDMS启动的时机还是比较早的,在整个Zygote进程刚刚开始要启动额时候就设置可用了;
    • 下面的循环主要是解析main方法的参数获取是否需要启动SystemService进程、获取abi列表、获取scoket连接名称 ;
      (这里需要注意的是:android系统中进程之间通讯的方式是Binder,但是有一个例外是SystemService进程与Zygote进程之间是通过Socket的方式进行通讯的)
    • 然后调用registerZygoteSocket(String socketName)为Zygote进程注册socket:

    2. main方法中调用的registerZygoteSocket方法

    作用是为Zygote进程注册socket

    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);
                }
            }
        }
    

    3. 接着调用系统方法preLoad()

    通过Zygote fork出SystemServer进程:

    static void preload() {
            Log.d(TAG, "begin preload");
            preloadClasses();
            preloadResources();
            preloadOpenGL();
            preloadSharedLibraries();
            preloadTextResources();
            // Ask the WebViewFactory to do any initialization that must run in the zygote process,
            // for memory sharing purposes.
            WebViewFactory.prepareWebViewInZygote();
            Log.d(TAG, "end preload");
        }
    

    这其中:
    preloadClasses()用于初始化Zygote中需要的class类;
    preloadResources()用于初始化系统资源;
    preloadOpenGL()用于初始化OpenGL;
    preloadSharedLibraries()用于初始化系统libraries;
    preloadTextResources()用于初始化文字资源;
    prepareWebViewInZygote()用于初始化webview;

    4. 然后调用startSystemServer(abiList, socket)方法

    private static boolean startSystemServer(String abiList, String socketName)
                throws MethodAndArgsCaller, RuntimeException {
            long capabilities = posixCapabilitiesAsBits(
                OsConstants.CAP_BLOCK_SUSPEND,
                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
            );
            /* 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,1032,3001,3002,3003,3006,3007",
                "--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 */
                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 */
            if (pid == 0) {
                if (hasSecondZygote(abiList)) {
                    waitForSecondaryZygote(socketName);
                }
    
                handleSystemServerProcess(parsedArgs);
            }
    
            return true;
        }
    

    ** 总结: **
    Zygote进程mian方法主要执行逻辑:

     - 初始化DDMS;
    
     - 注册Zygote进程的socket通讯;
    
     - 初始化Zygote中的各种类,资源文件,OpenGL,类库,Text资源等等;
    
     - 初始化完成之后fork出SystemServer进程;
    
     - fork出SystemServer进程之后,关闭socket连接;

    相关文章

      网友评论

          本文标题:Android源码分析--Zygote进程启动流程

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