zygote

作者: xuefeng_apple | 来源:发表于2020-05-05 17:19 被阅读0次

    本文主要介绍zygote 流程

    frameworks/base/cmds/app_process/app_main.cpp
    frameworks/base/core/jni/AndroidRuntime.cpp
    frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
    frameworks/base/core/java/com/android/internal/os/ZygoteConnection.java
    frameworks/base/core/java/com/android/internal/os/Zygote.java
    
    zygote zygote uml

    1 , 解析zygote 脚本,并运行main
    android/system/core/rootdir/init.zygote64.rc

    service zygote /system/bin/app_process64 -Xzygote /system/bin --zygote --start-system-server
        class main --> 启动app_process  可执行文件
        priority -20
        user root
        group root readproc
        socket zygote stream 660 root system---》创建/dev/socket/zygote
        onrestart write /sys/android_power/request_state wake
        onrestart write /sys/power/state on
        onrestart restart audioserver
        onrestart restart cameraserver
        onrestart restart media
        onrestart restart netd
        onrestart restart wificond
        writepid /dev/cpuset/foreground/tasks
    

    frameworks/base/cmds/app_process/app_main.cpp

    int main(int argc, char* const argv[])
    {
        while (i < argc) {  -----》解析zygote rc 中的参数
            const char* arg = argv[i++];
            if (strcmp(arg, "--zygote") == 0) {
                zygote = true;
                niceName = ZYGOTE_NICE_NAME;
            } else if (strcmp(arg, "--start-system-server") == 0) {
                startSystemServer = true;
            } else if (strcmp(arg, "--application") == 0) {
                application = true;
            } else if (strncmp(arg, "--nice-name=", 12) == 0) {
                niceName.setTo(arg + 12);
            } else if (strncmp(arg, "--", 2) != 0) {
                className.setTo(arg);
                break;
        }
        ...........
        if (zygote) {
            runtime.start("com.android.internal.os.ZygoteInit", args, zygote);---->启动zygote 
        } else if (className) {
            runtime.start("com.android.internal.os.RuntimeInit", args, zygote);
        } 
    }
    

    2 启动VM JNI
    从该函数 cpp-->java 启动java虚拟机
    frameworks/base/core/jni/AndroidRuntime.cpp

    /*
     * Start the Android runtime.  This involves starting the virtual machine
     * and calling the "static void main(String[] args)" method in the class
     * named by "className". --->仔细看这里的说明
     * Passes the main function two arguments, the class name and the specified
     * options string.
     */
    void AndroidRuntime::start(const char* className, const Vector<String8>& options, bool zygote)
    {
        JNIEnv* env;
        if (startVm(&mJavaVM, &env, zygote) != 0) {----------》启动VM
            return;
        }
        onVmCreated(env);
    
        /*
         * Register android functions.-------------》启动JNI 环境
         */
        if (startReg(env) < 0) {
            ALOGE("Unable to register all android natives\n");
            return;
        }
    
        /*
         * Start VM.  This thread becomes the main thread of the VM, and will
         * not return until the VM exits.
         */
        char* slashClassName = toSlashClassName(className != NULL ? className : "");
        jclass startClass = env->FindClass(slashClassName);
        if (startClass == NULL) {
            ALOGE("JavaVM unable to locate class '%s'\n", slashClassName);
            /* keep going */
        } else {
            jmethodID startMeth = env->GetStaticMethodID(startClass, "main",
                "([Ljava/lang/String;)V");
            if (startMeth == NULL) {
                ALOGE("JavaVM unable to find main() in '%s'\n", className);
                /* keep going */
            } else {
                env->CallStaticVoidMethod(startClass, startMeth, strArray);---->启动main , zygote init
            }
    }
    

    3 注册socket 加载资源 fork 等待
    frameworks/base/core/java/com/android/internal/os/ZygoteInit.java

        public static void main(String argv[]) {
            ZygoteServer zygoteServer = new ZygoteServer();
    
                for (int i = 1; i < argv.length; i++) {------->保存init.rc中设定zygote 参数
                    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]);
                    }
                }
    
                zygoteServer.registerServerSocket(socketName);--------》注册socket 
                preload(bootTimingsTraceLog);------》加载系统资源
    
                if (startSystemServer) {---------->第一次首先fork SystemServer, SystemServer单独讲解
                    Runnable r = forkSystemServer(abiList, socketName, zygoteServer);
                }
    
           caller = zygoteServer.runSelectLoop(abiList);------》
    -----》zygot 进入run selectloop. ---》connection.processOneCommand(this)----》forkAndSpecialize
    
        }
    

    frameworks/base/core/java/com/android/internal/os/Zygote.java

        /**
         * Special method to start the system server process. In addition to the
         * common actions performed in forkAndSpecialize, the pid of the child
         * process is recorded such that the death of the child process will cause
         * zygote to exit.
         *
         * @param uid the UNIX uid that the new process should setuid() to after
         * fork()ing and and before spawning any threads.
         * @param gid the UNIX gid that the new process should setgid() to after
         * fork()ing and and before spawning any threads.
         * @param gids null-ok; a list of UNIX gids that the new process should
         * setgroups() to after fork and before spawning any threads.
         * @param debugFlags bit flags that enable debugging features.
         * @param rlimits null-ok an array of rlimit tuples, with the second
         * dimension having a length of 3 and representing
         * (resource, rlim_cur, rlim_max). These are set via the posix
         * setrlimit(2) call.
         * @param permittedCapabilities argument for setcap()
         * @param effectiveCapabilities argument for setcap()
         *
         * @return 0 if this is the child, pid of the child
         * if this is the parent, or -1 on error.
         */
        public static int forkSystemServer(int uid, int gid, int[] gids, int debugFlags,
                int[][] rlimits, long permittedCapabilities, long effectiveCapabilities) {
            VM_HOOKS.preFork();
            // Resets nice priority for zygote process.
            resetNicePriority();--->rest 优先级
            int pid = nativeForkSystemServer(---->进入naitive C++ 函数, 进行了fork
                    uid, gid, gids, debugFlags, rlimits, permittedCapabilities, effectiveCapabilities);
            // Enable tracing as soon as we enter the system_server.
            if (pid == 0) {
                Trace.setTracingEnabled(true, debugFlags);
            }
            VM_HOOKS.postForkCommon();
            return pid;
        }
    

    4 资源加载解析preload
    启动过程中使用到了preload, 到底加载了哪些系统资源,共享资源进行预加载,独立的app运行,基本是使用过程加载。在preload整个过程中是禁止多线程。

        static void preload(TimingsTraceLog bootTimingsTraceLog) {
            Log.d(TAG, "begin preload");
            preloadClasses();  ------》加载class 
            preloadResources();   ---->加载resource
            nativePreloadAppProcessHALs();  ---->加载 APP hal resource
            preloadOpenGL();  ---->加载openGL 资源
            preloadSharedLibraries();---->加载共享库
            preloadTextResources();---->加载Text 资源
        }
    

    frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
    preloadClasses:基本思路,是读取,while line by line , 解析加载。

    private static String PRELOADED_CLASSES = "/system/etc/preloaded-classes";-->class 路径
    InputStream is = new FileInputStream(PRELOADED_CLASSES);  --》读取流
    BufferedReader br = new BufferedReader(new InputStreamReader(is), 256); -->读取到buf
        while ((line = br.readLine()) != null) {  ---->line读取
               try {
                    // Load and explicitly initialize the given class. Use
                    // Class.forName(String, boolean, ClassLoader) to avoid repeated stack lookups
                    // (to derive the caller's class-loader). Use true to force initialization, and
                    // null for the boot classpath class-loader (could as well cache the
                    // class-loader of this class in a variable).
                    Class.forName(line, true, null);------》上面解析基本说明了,class.forName()方法内部调用了this.getClass().getClassLoader()方法
                    count++;
                } catch (ClassNotFoundException e) {
    }
    

    frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
    frameworks/base/config/ preloaded-classes
    只列举部分的class , 因此通过Class.forName加载到系统中,生成字节码,系统启动过程需要一定时间

    android.R$styleable
    android.accessibilityservice.AccessibilityServiceInfo$1
    android.accounts.Account
    android.accounts.Account$1
    android.accounts.AccountManager
    android.accounts.AccountManager$1
    android.accounts.AccountManager$11
    android.accounts.AccountManager$AmsTask
    android.accounts.AccountManager$AmsTask$1
    android.accounts.AccountManager$AmsTask$Response
    android.accounts.AccountManager$BaseFutureTask
    android.accounts.AccountManager$BaseFutureTask$1
    android.accounts.AccountManager$BaseFutureTask$Response
    android.accounts.AccountManager$Future2Task
    android.accounts.AccountManagerFuture
    ............
    

    frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
    preloadResources:

        /**
         * Load in commonly used resources, so they can be shared across
         * processes.
         *
         * These tend to be a few Kbytes, but are frequently in the 20-40K
         * range, and occasionally even larger.
         */
        private static void preloadResources() {
            final VMRuntime runtime = VMRuntime.getRuntime();
    
            try {
                mResources = Resources.getSystem();
                mResources.startPreloading();
                if (PRELOAD_RESOURCES) {
                    Log.i(TAG, "Preloading resources...");
    
                    long startTime = SystemClock.uptimeMillis();
                    TypedArray ar = mResources.obtainTypedArray(--------》加载
                            com.android.internal.R.array.preloaded_drawables);
                    int N = preloadDrawables(ar);
                    ar.recycle();
                    Log.i(TAG, "...preloaded " + N + " resources in "
                            + (SystemClock.uptimeMillis()-startTime) + "ms.");
    
                    startTime = SystemClock.uptimeMillis();
                    ar = mResources.obtainTypedArray(--------》加载
                            com.android.internal.R.array.preloaded_color_state_lists);
                    N = preloadColorStateLists(ar);
                    ar.recycle();
                    Log.i(TAG, "...preloaded " + N + " resources in "
                            + (SystemClock.uptimeMillis()-startTime) + "ms.");
    
                    if (mResources.getBoolean(--------》加载
                            com.android.internal.R.bool.config_freeformWindowManagement)) {
                        startTime = SystemClock.uptimeMillis();
                        ar = mResources.obtainTypedArray(---------》加载
                                com.android.internal.R.array.preloaded_freeform_multi_window_drawables);
                       
                        //preloaded_freeform_multi_window_drawables 路径是:
                        frameworks/base/core/res/res/values/arrays.xml
                        上面的资源类似与apk 中layout 中的资源,window窗口大小,包括app 窗口
    
                        N = preloadDrawables(ar);
                        ar.recycle();
                        Log.i(TAG, "...preloaded " + N + " resource in "
                                + (SystemClock.uptimeMillis() - startTime) + "ms.");
                    }
                }
                mResources.finishPreloading();
            } catch (RuntimeException e) {
                Log.w(TAG, "Failure preloading resources", e);
            }
        }
    

    frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
    preloadColorStateLists
    下面是具体的参数TypedArray:
    com.android.internal.R.array.preloaded_color_state_lists

        private static int preloadColorStateLists(TypedArray ar) {
            int N = ar.length();
            for (int i=0; i<N; i++) {
                int id = ar.getResourceId(i, 0);
                if (false) {
                    Log.v(TAG, "Preloading resource #" + Integer.toHexString(id));
                }
                if (id != 0) {
                    if (mResources.getColorStateList(id, null) == null) {
                        throw new IllegalArgumentException(
                                "Unable to find preloaded color resource #0x"
                                + Integer.toHexString(id)
                                + " (" + ar.getString(i) + ")");
                    }
                }
            }
            return N;
        }
    

    frameworks/base/core/java/com/android/internal/os/ZygoteInit.java

    public static void main(String argv[]) {
         // Mark zygote start. This ensures that thread creation will throw an error.
         ZygoteHooks.startZygoteNoThreadCreation();  -------->开始禁止多线程
    
         registerServerSocket --->注册socket
         preload(bootTimingsTraceLog);--->加载资源       
         gcAndFinalize(); ---> // Do an initial gc to clean up after startup 
         ZygoteHooks.stopZygoteNoThreadCreation()-------->停止禁止多线程
         Runnable r = forkSystemServer(abiList, socketName, zygoteServer)
    }
    
    禁止多线程

    4 zygote 的socket 通信
    zygote 创建了/dev/socket/zygote , 系统如何调用socket 创建通信, 在下面的文章中进行讲解registerServerSocket

    zygoteInit::main--->
             registerServerSocket--->
             preload---->
             forkSystemServer--->
    

    总体概述:
    https://www.cnblogs.com/monsterdev/p/12685091.html
    https://blog.csdn.net/chz429/article/details/87514718

    相关文章

      网友评论

          本文标题:zygote

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