2.Android 小米权威专家彻底分析 Zygote进程启动 (基于安卓12系统)

启动SystemServer进程
接下来查看 startSystemServer函数,代码如下所示。
 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,3009,3010",
            "--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);//2
            ZygoteConnection.applyDebuggerSystemProperty(parsedArgs);
            ZygoteConnection.applyInvokeWithSystemProperty(parsedArgs);
            /*3*/
            pid = Zygote.forkSystemServer(
                    parsedArgs.uid, parsedArgs.gid,
                    parsedArgs.gids,
                    parsedArgs.debugFlags,
                    null,
                    parsedArgs.permittedCapabilities,
                    parsedArgs.effectiveCapabilities);
        } catch (IllegalArgumentException ex) {
            throw new RuntimeException(ex);
        }
        if (pid == 0) {
            if (hasSecondZygote(abiList)) {
                waitForSecondaryZygote(socketName);
            }
            handleSystemServerProcess(parsedArgs);//4
        }
        return true;
    }
---------------------------------------------------
Java里面的调用:
public class ZygoteInit {
public static void main(String argv[]) {
    ZygoteServer zygoteServer = new ZygoteServer();

    // Mark zygote start. This ensures that thread creation will throw
    // an error.
    ZygoteHooks.startZygoteNoThreadCreation();

    // Zygote goes into its own process group.
    try {
        Os.setpgid(0, 0);
    } catch (ErrnoException ex) {
        throw new RuntimeException("Failed to setpgid(0,0)", ex);
    }

    final Runnable caller;
    try {
        // Report Zygote start time to tron unless it is a runtime restart
        if (!"1".equals(SystemProperties.get("sys.boot_completed"))) {
            MetricsLogger.histogram(null, "boot_zygote_init",
                    (int) SystemClock.elapsedRealtime());
        }

        String bootTimeTag = Process.is64Bit() ? "Zygote64Timing" : "Zygote32Timing";
        TimingsTraceLog bootTimingsTraceLog = new TimingsTraceLog(bootTimeTag,
                Trace.TRACE_TAG_DALVIK);
        bootTimingsTraceLog.traceBegin("ZygoteInit");
        RuntimeInit.enableDdms();

        boolean startSystemServer = false;
        String socketName = "zygote";
        String abiList = null;
        boolean enableLazyPreload = false;
        for (int i = 1; i < argv.length; i++) {
            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]);
            }
        }

        if (abiList == null) {
            throw new RuntimeException("No ABI list supplied.");
        }

        zygoteServer.registerServerSocketFromEnv(socketName);
        // In some configurations, we avoid preloading resources and classes eagerly.
        // In such cases, we will preload things prior to our first fork.
        if (!enableLazyPreload) {
            bootTimingsTraceLog.traceBegin("ZygotePreload");
            EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_START,
                SystemClock.uptimeMillis());
            preload(bootTimingsTraceLog);
            EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_END,
                SystemClock.uptimeMillis());
            bootTimingsTraceLog.traceEnd(); // ZygotePreload
        } else {
            Zygote.resetNicePriority();
        }

        // Do an initial gc to clean up after startup
        bootTimingsTraceLog.traceBegin("PostZygoteInitGC");
        gcAndFinalize();
        bootTimingsTraceLog.traceEnd(); // PostZygoteInitGC

        bootTimingsTraceLog.traceEnd(); // ZygoteInit
        // Disable tracing so that forked processes do not inherit stale tracing tags from
        // Zygote.
        Trace.setTracingEnabled(false, 0);

        Zygote.nativeSecurityInit();

        // Zygote process unmounts root storage spaces.
        Zygote.nativeUnmountStorageOnInit();

        ZygoteHooks.stopZygoteNoThreadCreation();

        if (startSystemServer) {
            Runnable r = forkSystemServer(abiList, socketName, zygoteServer);

            // {@code r == null} in the parent (zygote) process, and {@code r != null} in the
            // child (system_server) process.
            if (r != null) {
                r.run();
                return;
            }
        }

        Log.i(TAG, "Accepting command socket connections");

        // The select loop returns early in the child process after a fork and
        // loops forever in the zygote.
        caller = zygoteServer.runSelectLoop(abiList);
    } catch (Throwable ex) {
        Log.e(TAG, "System zygote died with exception", ex);
        throw ex;
    } finally {
        zygoteServer.closeServerSocket();
    }

    // We're in the child process and have exited the select loop. Proceed to execute the
    // command.
    if (caller != null) {
        caller.run();
    }
}
servermanager进程是在zygote init进程之前
他们都是ini孵化出来的---------------------

Zygote启动流程就讲到这,Zygote进程共做了如下几件事:

1.创建AppRuntime并调用其start方法,启动Zygote进程。

2.通过JNI调用ZygoteInit的main函数进入Zygote的Java框架层。(ZygoteInit.java).换句换说Zygote开创了Java框架层

3.ZygoteInit这个类 ,里面有个懒加载!它还有什么用,它会加载很多很多类。preload_class..把系统公共的累加载到系统内存

4.里面有个zygotesever,是用socket,通过registerZygoteSocket创建服务端Socket,并通过runSelectLoop函数等待ActivityManagerService的请求来创建新的应用程序进程。

5.启动SystemServer进程。

看看里面的源码,调用方法

最后再来总结一下:

Zygote 进程是由 init 进程解析 init.rc 脚本创建的,其具体的执行源码是在 App_main.main 方法,

首先会创建一个虚拟机实例,然后注册 JNI 方法,最后通过 JNI 调用进入 Java 世界来到 ZygoteInit.main 方法。

在 Java 世界中我们会为 Zygote 注册 socket 用于进程间通信,预加载一些通用的类和资源,

启动 system_server 进程,循环等待孵化创建新的进程。

4步:

1.创建虚拟机

2.预加载资源

3.循环等待孵化创建新的进程

Zygote 最后是一个死循环,不断的等待远程跟我通信,创建子进程
 Os.poll(pollFds, -1);  会阻塞等待有没有新的文件描述符发生变化

4.启动SystemServer进程。

问题:为什么预加载资源?

因为其他应用都是通zygote进程创建,资源可以共享,继承父进程的资源!copyOnWrite

所有的 app 进程都是由 Zygote 孵化(fork)而来的。fork 有一个 copyonwrite 技术可以复用父进程的资源,好处就是不需要再去额外的花费时间去加载资源,
不好的地方:进程一创建他的内存就比较大

问题:资源加载加载了哪些资源?

android.jar。openGL等!


private static void preloadSharedLibraries() {
    Log.i(TAG, "Preloading shared libraries...");
    System.loadLibrary("android");
    System.loadLibrary("compiler_rt");
    System.loadLibrary("jnigraphics");

    try {
        System.loadLibrary("sfplugin_ccodec");
    } catch (Error | RuntimeException e) {
        // tolerate missing sfplugin_ccodec which is only present on Codec 2 devices
    }
}

/**
 * This call loads the graphics driver by making an OpenGL or Vulkan call.  If the driver is
 * not currently in memory it will load and initialize it.  The OpenGL call itself is relatively
 * cheap and pure.  This means that it is a low overhead on the initial call, and is safe and
 * cheap to call later.  Calls after the initial invocation will effectively be no-ops for the
 * system.
 */
static native void nativePreloadGraphicsDriver();

private static void maybePreloadGraphicsDriver() {
    if (!SystemProperties.getBoolean(PROPERTY_DISABLE_GRAPHICS_DRIVER_PRELOADING, false)) {
        nativePreloadGraphicsDriver();
    }
}

问题:如何优化开机启动?

资源加载方面通过多线程

问题:应用开发为什么要用多进程:

QQ音乐(9个进程),获取更多资源,进程之间相互不影响,为了有更好的体验!

可以优化启动速度:很多加载库不用一开始就加载,可以先看到页面,然后再是音乐播放

因为多个进程,application会执行多次,不同进程加载不同的内容!

优化启动速度:可以用多线程么?

问题:zygote进程是init如何创建的?
Zygote 进程是由 init 进程解析 init.rc 脚本创建的

问题: zygote是由什么进程创建的

init进程

问题:  为什么要设计zygote?

因为同一用它来创建进程,方便管理

为什么zygote进程通信的时候用socket,不用binder?

因为安全,binder容易被hook,还没有启动相关的东西, 第二点:为了cs架构的设计理念!

问题:zygote进程如果挂了会怎么样?

手机会重启,因为很多服务用不了

问题:zygote进程是如何从c进程转到java进程

jni, C调用java 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值