AndroidP_Zygote进程源码梳理从认识到理解

  • Post author:
  • Post category:其他




前言

还是来看看,Zygote进程吧,这个和日常开发的关系还是很紧密的,我们今天对它的创建,启动和工作的方面对Zygote进程来梳理一下:



怎么理解Zygote

zygote,硬翻过来是受精卵的意思, 我们先大概的认识下:

  • zygote进程是由init进程创建的;init管理zygote的生命周期;
  • 系统中大部分应用进程是从zygote直接或者间接创建的;
  • zygote进程在Android系统的全生命周期都是存活的,守护并管理这他的子孙;

基于上面的总体映像.我们到到代码中去看看:



代码梳理



1. 程序的起点

首先,我们在init.rc文件中看到,

import /init.${ro.zygote}.rc

看到上面,我们就可以猜到zygote也会和init进程一样有一个rc文件了,我们我们连接设备,在终端执行

adb shell

.然后

ls

,就会出现下图显示的文件(当然,这需要开发版本的设备才能看得到)

在这里插入图片描述

init程序在解析了自身的init.rc文件后,当处理到zygte的相关条目时,就会去启动zygote进程(这个过程就不在深入,):

我们先了zygote的rc文件是怎样子的:

service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server
    class main
    priority -20
    user root
    group root readproc reserved_disk
    socket zygote stream 660 root system
    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

如上,对rc文件的语法和内容就不在具体深入,可参考

system/core/rootdir/README.md

;

程序在读取到第一行的时候,就知道,接下来创建的程序有自己名称,独立运行代码路径,启动参数,

记下来我们就要去zygote的代码中一探究竟:



2.app_main


注意

:当程序走到这个文件的时候,

zygote所在的进程是已经创建好了,socket

,近下来干的事情更像是zygote初始化.

老这样,我们先来到app_main.cpp文件的main()方法:

int main(int argc, char* const argv[])
{
    std::string bootmode = GetProperty("ro.bootmode", "");
	//这是高通平台的内容,我查看了aosp的代码,没有这块,这个我们就不去具体分析了,下面代码不关乎大的流程的小细节都略过
    if ((strncmp(bootmode.c_str(), "ffbm-00", 7) == 0)
            || (strncmp(bootmode.c_str(), "ffbm-01", 7) == 0)) {
            return 0;
    }
    ...
    // Parse runtime arguments.  Stop at first unrecognized option.
    // 这里就是在解析zygote的rc文件传的参数了,,我们看过rc文件,这里的参数也就很清楚是什么了;
    // 所以下面的startSystemServer = true;zygote = true;
    bool zygote = false;
    bool startSystemServer = false;
    bool application = false;
    String8 niceName;
    String8 className;
    ++i;  // Skip unused "parent dir" argument.
    while (i < argc) {
        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;
        } else {
            --i;
            break;
        }
    }
    ...
    // 说明接下来在zygote初始化好后,是需要创建systemServer进程的
    if (startSystemServer) {
        args.add(String8("start-system-server"));
    }
    ...
    // 现在runtime.需要到"com.android.internal.os.ZygoteInit"去继续运行,当期那的代码就算是走完了
    if (zygote) {
        runtime.start("com.android.internal.os.ZygoteInit", args, zygote);
    }
    ...

如上所示,从rc文件中的zygote的代码主要这些内容,然后就会调用runtime的start()函数继续执行,



2.1 appRuntime和AndroidRuntime

我们先看看这个runtime是个什么东西.runtime是AppRuntime的一个实例,AppRuntime类继承自AndroidRuntime;


frameworks/base/core/jni/include/android_runtime/AndroidRuntime.h



frameworks/base/core/jni/AndroidRuntime.cpp


  • AndroidRuntime

    : 这里的代码就不贴出来了,我们可以认为AndroidRuntime这个类就是供创建VM(虚拟机),供Java和native之间相互调用的中介.因为其中有创建VM的函数

    startVM()

    ,VM创建完成的回调函数

    onStarted(),onZygoteInit()

    ,Native层查找Java层的类以及调用java方法的函数

    findClass()和callMain()

    ,以及大量注册jni方法的数组

    RegJNIRec

    等等

  • AppRuntime

    我们又该怎么理解这个AppRuntime呢?因为AppRuntime是继承自AndroidRuntime,

    并且其内部并主要还是重写了AndroidRuntime一些方法,那我们就将AppRuntime和AndroidRuntime同等看待.



2.2 AndroidRuntime.start()

本来是调用appRuntime的start()函数,appRuntime是继承AndroidRuntime,这里其实是调用AndroidRuntime.start()函数:


这就是我们的zygote升级的关键,要从native层跳到java层去了;要运行java,就得要依赖虚拟机毕竟Java语言与系统无关

void AndroidRuntime::start(const char* className, const Vector<String8>& options, bool zygote)
//我们很清楚传进来的参数是什么(忘记了的话网上翻翻)
{
	...
    /* start the virtual machine */
    //这个就注解就很好,我就不翻译了
    JniInvocation jni_invocation;
    jni_invocation.Init(NULL);
    JNIEnv* env;
    if (startVm(&mJavaVM, &env, zygote) != 0) {
        return;
    }
    onVmCreated(env);
    /*
     * Register android functions.
     */
    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);

}
...

如上所示: start()函数内主要做了三件大事

  1. 创建VM
  2. 注册Native函数
  3. 查找Java类以及Java方法,然后跳转到Java层去执行,


说明

:zygote初始化过程中创建VM, zygote创建应用进程的时候,应用进程就会获得zygote的资源,当然也有VM

准确的说应该是克隆了zygote的所有资源



3. ZygoteInit

接下来我们就要从native层进入Java层了,首先我们看ZygoteInit:


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

public static void main(String argv[]) {
	// 一开始就new了个ZygoteServer类的实例,这个ZygoteServer是个socket服务端,
     ZygoteServer zygoteServer = new ZygoteServer();
    // Zygote goes into its own process group.
    Os.setpgid(0, 0);
    ...
    //注册用于zygote命令连接的socket的server,socket的fd在通过ANDROID_SOCKET_环境变量获取.
    zygoteServer.registerServerSocketFromEnv(socketName);
	// 预加载资源,常见类,共享库,文字图片资源等
    preload(bootTimingsTraceLog);
    ...
    // 访问安全设置
   Zygote.nativeSecurityInit();
   // Zygote process unmounts root storage spaces.
   Zygote.nativeUnmountStorageOnInit();
   ...
   //创建systemServer进程
   Runnable r = forkSystemServer(abiList, socketName, zygoteServer);
   // The select loop returns early in the child process after a fork and
   // loops forever in the zygote.
   caller = zygoteServer.runSelectLoop(abiList);

通过上面的主要方法的简述,我们就总体知道zygote在Java层做了那些事简单的终结就是

  • 注册socket server端
  • 预加载资源,这些资源的,zygote不一定会用,但是这个工作不白做,因为应用在被创建后可以直接拷贝zygote加载的这些资源,【哈哈,zygote就是这么好.为子孙尽心尽力】
  • 然后创建systemServer进程,这是Android系统的很重要服务.
  • 最后进入zygoteServer的成员runSelectLoop()方法.这就是进入了一个循环,会监听之前创建的socket有没有新的请求,主要是来自AMS的创建应用的请求.



4 总结

1.init进程在native层创建zygote进程,

2. 然后进zygote的初始化(创建VM.注册native方法,跳转Java层)

3.进入Java层,监听socket用于通信,预加载资源,

4. 最后进入lop循环,等待请求并处理



版权声明:本文为weixin_38140931原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。