Androidシステム起動シリーズ---Zygoteプロセス

13407 ワード

引用する
前の文章Androidシステム起動シリーズ---initプロセス、大体分析して、initプロセスの起動過程.最後にZygoteプロセスはapp_プロセスプロセスはJNIによってZygoteInitのmainメソッドを呼び出して開始される.この文章はZygoteプロセスが私たちのために何をしたかを分析します.(システムソース分析はAndroid 6.0.1に基づく)
Zygote機能
まずZygoteInitのmainメソッドを見てみましょう(/frameworks/base/core/java/com/android/internal/os/ZygoteInit.java)
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);       //  1
            EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_START,
                SystemClock.uptimeMillis());
            preload();          //  2
            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);   //  3
            }

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

            closeServerSocket();
        } catch (MethodAndArgsCaller caller) {
            caller.run();   //  5
        } catch (RuntimeException ex) {
            Log.e(TAG, "Zygote died with exception", ex);
            closeServerSocket();
            throw ex;
        }
    }
  • 注記1:socket通信を登録するサービス側
  • 注記2:プリロード
  • 注記3:SystemServerシステムサービス
  • を開始
  • 注記4:socketクライアントの接続要求(新しいアプリケーションappの起動など)
  • をループ待機する.
  • 注記5:socketクライアントを実行するリクエスト者のmainメソッド
  • を実行する
    SOcket通信のサービス・エンドの登録(registerZygoteSocket)
    「zygote」という名前のsocketserverを登録します.
    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);  // 1
                } catch (IOException ex) {
                    throw new RuntimeException(
                            "Error binding to local socket '" + fileDesc + "'", ex);
                }
            }
        }
    

    注記1:serversocket静的オブジェクトを作成する
    プリロード
    static void preload() {
            Log.d(TAG, "begin preload");
            preloadClasses();               //         class   
            preloadResources();           //         
            preloadOpenGL();                //     OpenGL      
            preloadSharedLibraries();    //         so : android、jnigraphics so 
            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");
        }
    

    SystemServerシステムサービスの起動
    /**
         * Prepare the arguments and fork for the system server process.
         */
        private static boolean startSystemServer(String abiList, String socketName)
                throws MethodAndArgsCaller, RuntimeException {
                
                .....
                
            /* Hardcoded command line to start the system server */
            //////////////////////  1
            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 */
                //////////////////////  2
                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);
                }
                //////////////////////  3
                handleSystemServerProcess(parsedArgs);
            }
    
            return true;
        }
    

    a.注釈1:システムサーバを起動するいくつかのパラメータを設定するb.注釈2:パラメータforkに従ってシステム_サーバのプロセス
    public static int forkSystemServer(int uid, int gid, int[] gids, int debugFlags,
                int[][] rlimits, long permittedCapabilities, long effectiveCapabilities) {
            VM_HOOKS.preFork();
            int pid = nativeForkSystemServer(
                    uid, gid, gids, debugFlags, rlimits, permittedCapabilities, effectiveCapabilities);
            // Enable tracing as soon as we enter the system_server.
            if (pid == 0) {
                Trace.setTracingEnabled(true);
            }
            VM_HOOKS.postForkCommon();
            return pid;
        }
    

    nativeForkSystemServerメソッドはnativeローカルメソッドの役割であり、forkのSystemServerプロセスである.
    c.注釈3:注釈2のpid=0でifの文がSystemServerプロセスで実行することを示すcomを起動する.android.server.SystemServerクラスのmainメソッド.
    private static void handleSystemServerProcess(
                ZygoteConnection.Arguments parsedArgs)
                throws ZygoteInit.MethodAndArgsCaller {
    
            .......
    
            if (parsedArgs.invokeWith != null) {
                String[] args = parsedArgs.remainingArgs;
                ........
    
                WrapperInit.execApplication(parsedArgs.invokeWith,
                        parsedArgs.niceName, parsedArgs.targetSdkVersion,
                        VMRuntime.getCurrentInstructionSet(), null, args);
            } else {
                ClassLoader cl = null;
                if (systemServerClasspath != null) {
                    cl = new PathClassLoader(systemServerClasspath, ClassLoader.getSystemClassLoader());
                    Thread.currentThread().setContextClassLoader(cl);
                }
    
                /*
                 * Pass the remaining arguments to SystemServer.
                 */
                 //////////////////////////// 1
                RuntimeInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs, cl);
            }
        }
    

    注記1システムサーバのいくつかのパラメータをRuntimeInitに入力します.zygoteInitメソッド.もう一度見てみろzygoteInitメソッド:
    public static final void zygoteInit(int targetSdkVersion, String[] argv, ClassLoader classLoader)
                throws ZygoteInit.MethodAndArgsCaller {
                
            ......
            
            nativeZygoteInit();       ///////////////////  1
            applicationInit(targetSdkVersion, argv, classLoader);     /////////////////////////  2
        }
    
  • 注記1:nativeレイヤはいくつか初期化されており、nativeメソッドは/frameworks/base/core/jni/Android Runtimeに対応する.JAvaで.
    static void com_android_internal_os_RuntimeInit_nativeZygoteInit(JNIEnv* env, jobject clazz)
    {
        gCurRuntime->onZygoteInit();
    }
    
    onZygoteInitは虚関数で、その実装クラスはどこにあるのか、前の記事app_を覚えています.プロセスのapp_main.cppファイルにAppRuntimeクラスはありますかruntime.start()はZygoteプロセスを開始し,AppRutimeクラスはAndroid Runtimeを継承しonZygoteInitメソッドを実現した.
    virtual void onZygoteInit()
        {
            sp proc = ProcessState::self();
            ALOGV("App process: starting thread pool.
    "); proc->startThreadPool(); }
    ここでprocは、binderのスレッドプールであり、後でbinderスレッドプールを詳細に分析し、プロセス間の通信に使用します.
  • 注記2:java層の初期化アプリケーションInit()
  • private static void applicationInit(int targetSdkVersion, String[] argv, ClassLoader classLoader)
                throws ZygoteInit.MethodAndArgsCaller {
            
            .......
            
            // Remaining arguments are passed to the start class's static main
            invokeStaticMain(args.startClass, args.startArgs, classLoader);
        }
    

    invokeStaticMainメソッドを続行します.
    private static void invokeStaticMain(String className, String[] argv, ClassLoader classLoader)
                throws ZygoteInit.MethodAndArgsCaller {
            Class> cl;
    
            try {
            /////////////////////   1
                cl = Class.forName(className, true, classLoader);
            } catch (ClassNotFoundException ex) {
                throw new RuntimeException(
                        "Missing class when invoking static main " + className,
                        ex);
            }
    
            Method m;
            try {
            ///////////////////    2
                m = cl.getMethod("main", new Class[] { String[].class });
            } catch (NoSuchMethodException ex) {
                throw new RuntimeException(
                        "Missing static main on " + className, ex);
            } catch (SecurityException ex) {
                throw new RuntimeException(
                        "Problem getting static main on " + className, ex);
            }
    
            int modifiers = m.getModifiers();
            if (! (Modifier.isStatic(modifiers) && Modifier.isPublic(modifiers))) {
                throw new RuntimeException(
                        "Main method is not public and static on " + className);
            }
    
            ///////////////////    3
            throw new ZygoteInit.MethodAndArgsCaller(m, argv);
        }
    

    私たちは一緒に降りてclassNameに入るのがcomだと知っています.android.server.SystemServer注記1:Classを反射する.forNameはcomをロードします.android.server.SystemServerのSystemServerclassオブジェクト.注記2:SystemServerを介して.classオブジェクトのSystemServerのmainメソッドを取得するMethodオブジェクト.注釈3:この方法は終わっても実際にinvoke SystemServerのmain方法を反射するのではなくZygoteInitを投げ出した.MethodAndArgsCaller異常はmainメソッドのMethodオブジェクトとパラメータを入力します.明らかにこの異常類が処理したに違いない.じゃあどこを見つけるんだ?catchはこの異常情報を処理した.最終的には最初のZygoteInitで見ることができます.main()メソッド.
    try{
    ......
    } catch (MethodAndArgsCaller caller) {
                caller.run();   //  5
            } 
    
    public static class MethodAndArgsCaller extends Exception
                implements Runnable {
            /** method to call */
            private final Method mMethod;
    
            /** argument array */
            private final String[] mArgs;
    
            public MethodAndArgsCaller(Method method, String[] args) {
                mMethod = method;
                mArgs = args;
            }
    
            public void run() {
                try {
                    mMethod.invoke(null, new Object[] { mArgs });  ///////////   1
                } catch (IllegalAccessException ex) {
                    throw new RuntimeException(ex);
                } catch (InvocationTargetException ex) {
                    Throwable cause = ex.getCause();
                    if (cause instanceof RuntimeException) {
                        throw (RuntimeException) cause;
                    } else if (cause instanceof Error) {
                        throw (Error) cause;
                    }
                    throw new RuntimeException(ex);
                }
            }
        }
    

    注記1:mMethodオブジェクトは、前述のSystemServerのmainメソッドのMethodオブジェクトであり、invokeによってmainメソッドが呼び出されます.これでシステムサーバはmainメソッドを実行します.
    新しいアプリケーションappの起動など、socketクライアントの接続要求をループします.
    ここでは詳しくは説明しませんが、while(true)はクライアントのリクエストを絶えず待っています.
    SOcketクライアントを呼び出すリクエスト者からのMehodオブジェクトメソッドの実行
    ここで,1つの処理は,前述のMethodAndArgsCallerクラスにおけるrun()法の処理で解析された.
    まとめ
  • app_を通過プロセスはZygoteInitを起動する.main()関数.
  • はまずserverSocketを登録しました.
  • forkはSystemServerプロセスを開始し、nativeメソッドでbinderスレッドプールを開き、SytemServerに提供してプロセス間通信を容易にします.
  • socketクライアントの接続要求
  • を待つ.