zygote

2020-05-05  本文已影响0人  xuefeng_apple

本文主要介绍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

上一篇下一篇

猜你喜欢

热点阅读