20.Androidソース分析--Zygoteプロセス起動プロセス

7825 ワード

AndroidシステムのZygoteプロセスは、SystemServerを含むすべてのandroidプロセスの親プロセスであり、Zygoteプロセスforkによって様々なアプリケーションプロセスが生成されます.ZygoteプロセスはLinuxシステムのinitプロセスによって起動されます.
Androidシステムにおける各種プロセスの起動方法:initプロセス->Zygoteプロセス->SystemServerプロセス->各種応用プロセス
  • initプロセス:linuxのルートプロセス;Androidシステムはlinuxシステムに基づいているため、androidオペレーティングシステム全体の最初のプロセスとみなすことができる.
  • Zygoteプロセス:androidシステムのルートプロセス;主な役割:fork出SystemServerプロセスと各種応用プロセス;
  • System Serviceプロセス:主にこのプロセスでシステムの各サービスを起動する.例えば、Activity Management Service、PackageManagement Service、WindowManagerServiceなど.
  • 各種アプリケーションプロセス:自分で作成したクライアントアプリケーションを起動する時、普通はすべて1つのアプリケーションプロセスを再起動して、自分の仮想機と運行環境があります;

  • ここでは主にZygoteプロセスの起動プロセスについて説明しますが、SystenServerプロセスと各種アプリケーションプロセスの起動方法については後述します.

    1.Zygoteクラスのmainメソッド


    InitプロセスはZygoteプロセスを起動する際に一般的にZygoteInitクラスのmainメソッドを呼び出すので、ここではこのメソッドの具体的な実装(android 23ソースコードに基づく)を見てみましょう.
    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 ;