Android系统从init进程到Launcher(二)

2021-10-23  本文已影响0人  猫咪不吃鱼

前言

Android 系统中,DVMART、应用程序进程以及运行系统的关键服务的 SystemServer 进程都是由 Zygote 进程来创建的。它通过 fock 的形式来创建应用程序进程和 SystemServer 进程,由于 Zygote 进程在启动时会创建 DVMART,因此通过 fock 而创建的应用程序进程和 SystemServer 进程可以在内部获取一个 DVM 或者 ART 的实例副本。

Zygote 进程任务

  1. 创建 AppRuntime 并调用其start 方法,启动 Zygote 进程
  2. 创建 Java 虚拟机并为 Java 虚拟机注册 JNI 方法
  3. 通过 JNI 调用 Zygote 的 main 函数进入 Zygote 的 Java 框架层
  4. 通过 registerZygoteSocket 方法创建服务器端 Socket,并通过 runSelectLoop 方法等待AMS 的请求来创建新的应用程序进程
  5. 启动 SystemServer 进程

Zygote 启动脚本

init.rc 文件中采用了 Import 类型语句引入 Zygote 启动脚本:

import /init.environ.rc
import /init.usb.rc
import /init.${ro.hardware}.rc
import /vendor/etc/init/hw/init.${ro.hardware}.rc
import /init.usb.configfs.rc
// ro.zygote 由硬件来决定引入的是32位还是64位
import /init.${ro.zygote}.rc

on early-init
    # Set init and its forked children's oom_adj.
    write /proc/1/oom_score_adj -1000
......

这里我们以 64 位程序为例:/system/core/rootdir/init.zygote64.rc

service zygote /system/bin/app_process64 -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

上面的代码中可以看出,Zygote 进程名称为 zygote,执行程序为 app_processclassnamemain ,当 server 重启的时候,会重启 audioserver、cameraserver、media、netd、wificond 进程;而 app_process 进程对应的源文件路径在 /frameworks/base/cmds/app_process/app_main.cpp

init 启动 Zygote 时主要是调用 app_main.cppmain 函数中的 AppRuntimestart 方法来启动 Zygote 进程,其时序图如下:

1. app_main.cpp # main函数源码分析

/frameworks/base/cmds/app_process/app_main.cpp

int main(int argc, char* const argv[])
{
    
    // argv = “/system/bin/app_process -Xzygote /system/bin --zygote --start-system-server”

    AppRuntime runtime(argv[0], computeArgBlockSize(argc, argv));
    argc--; // 跳过第一个参数/system/bin/app_precess
    argv++;

    
    // -Xzygote为虚拟机参数,在启动虚拟机是传递到虚拟机
    int i;
    for (i = 0; i < argc; i++) {
        if (known_command == true) {
          runtime.addOption(strdup(argv[i]));
          // The static analyzer gets upset that we don't ever free the above
          // string. Since the allocation is from main, leaking it doesn't seem
          // problematic. NOLINTNEXTLINE
          ALOGV("app_process main add known option '%s'", argv[i]);
          known_command = false;
          continue;
        }

        for (int j = 0;
             j < static_cast<int>(sizeof(spaced_commands) / sizeof(spaced_commands[0]));
             ++j) {
          if (strcmp(argv[i], spaced_commands[j]) == 0) {
            known_command = true;
            ALOGV("app_process main found known command '%s'", argv[i]);
          }
        }

        if (argv[i][0] != '-') {
            break;
        }
        if (argv[i][1] == '-' && argv[i][2] == 0) {
            ++i; // Skip --.
            break;
        }

        runtime.addOption(strdup(argv[i]));

    }

    // Parse runtime arguments.  Stop at first unrecognized option.
    bool zygote = false;
    bool startSystemServer = false;
    bool application = false;
    String8 niceName;
    String8 className;

    ++i;  // 跳过 /system/bin参数
    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;
        }
    }

    Vector<String8> args;
    if (!className.isEmpty()) {
        // We're not in zygote mode, the only argument we need to pass
        // to RuntimeInit is the application argument.
        //
        // The Remainder of args get passed to startup class main(). Make
        // copies of them before we overwrite them with the process name.
        args.add(application ? String8("application") : String8("tool"));
        runtime.setClassNameAndArgs(className, argc - i, argv + i);

        if (!LOG_NDEBUG) {
          String8 restOfArgs;
          char* const* argv_new = argv + i;
          int argc_new = argc - i;
          for (int k = 0; k < argc_new; ++k) {
            restOfArgs.append("\"");
            restOfArgs.append(argv_new[k]);
            restOfArgs.append("\" ");
          }
          ALOGV("Class name = %s, args = %s", className.string(), restOfArgs.string());
        }
    } else {
        // We're in zygote mode.
        maybeCreateDalvikCache();

        if (startSystemServer) {
            args.add(String8("start-system-server"));
        }

        char prop[PROP_VALUE_MAX];
        if (property_get(ABI_LIST_PROPERTY, prop, NULL) == 0) {
            LOG_ALWAYS_FATAL("app_process: Unable to determine ABI list from property %s.",
                ABI_LIST_PROPERTY);
            return 11;
        }

        String8 abiFlag("--abi-list=");
        abiFlag.append(prop);
        args.add(abiFlag);

        // In zygote mode, pass all remaining arguments to the zygote
        // main() method.
        for (; i < argc; ++i) {
            args.add(String8(argv[i]));
        }
    }

    // 修改线程名为zygote
    if (!niceName.isEmpty()) {
        runtime.setArgv0(niceName.string(), true /* setProcName */);
    }

    // 根据得到的参数调用com.android.internal.os.ZygoteInit
    // args这个vector中包含两个成员,args[0] = “start-system-server”
    // args[1] = “—abi-list=xxx” xxx代码的是CPU的结构,比如armeabi-v7a, arm64-v8a
    if (zygote) {
       // 注释②
        runtime.start("com.android.internal.os.ZygoteInit", args, zygote);
    } else if (className) {
        runtime.start("com.android.internal.os.RuntimeInit", args, zygote);
    } else {
        fprintf(stderr, "Error: no class name or --zygote supplied.\n");
        app_usage();
        LOG_ALWAYS_FATAL("app_process: no class name or --zygote supplied.");
    }
}

根据前面所述,Zygote 进程是通过 fock 自身来创建子进程的,这样 Zygote 进程和由它所创建的子进程都会进入到 app_main.cppmain 函数中,因此在 注释① 处会做判断当前是运行在哪个进程中。
注释② 处判断 zygotetrue ,则说明当前运行在 Zygote 进程中,就会调用 AppRuntimestart 函数。

AppRuntime类的声明和实现都在App_main.cpp中,它是从AndroidRuntime类派生出来的,代码如下:

frameworks/base/core/jni/AndroidRuntime.cpp

// className = "com.android.internal.os.ZygoteInit", options包含两个string8成员
// args[0] = “start-system-server” args[1] = “—abi-list=xxx”, zygote = true
void AndroidRuntime::start(const char* className, const Vector<String8>& options, bool zygote)
{
    ALOGD(">>>>>> START %s uid %d <<<<<<\n",
            className != NULL ? className : "(unknown)", getuid());

    static const String8 startSystemServer("start-system-server");

    /*
     * 'startSystemServer == true' means runtime is obsolete and not run from
     * init.rc anymore, so we print out the boot start event here.
     */
    for (size_t i = 0; i < options.size(); ++i) {
        if (options[i] == startSystemServer) {
           /* track our progress through the boot sequence */
           const int LOG_BOOT_PROGRESS_START = 3000;
           LOG_EVENT_LONG(LOG_BOOT_PROGRESS_START,  ns2ms(systemTime(SYSTEM_TIME_MONOTONIC)));
        }
    }

    const char* rootDir = getenv("ANDROID_ROOT");
    if (rootDir == NULL) {
        rootDir = "/system";
        if (!hasDir("/system")) {
            LOG_FATAL("No root directory specified, and /android does not exist.");
            return;
        }
        setenv("ANDROID_ROOT", rootDir, 1);
    }

    // 创建并启动虚拟机
    JniInvocation jni_invocation;
    jni_invocation.Init(NULL);
    JNIEnv* env;
    if (startVm(&mJavaVM, &env, zygote) != 0) {
        return;
    }
    onVmCreated(env);

    // 设置虚拟机的JNI环境
    if (startReg(env) < 0) {
        ALOGE("Unable to register all android natives\n");
        return;
    }

    // 调用JNI方法调用com.android.internal.os.ZygoteInit中的main方法
    jclass stringClass;
    jobjectArray strArray;
    jstring classNameStr;

    stringClass = env->FindClass("java/lang/String");
    assert(stringClass != NULL);
    strArray = env->NewObjectArray(options.size() + 1, stringClass, NULL);
    assert(strArray != NULL);
    classNameStr = env->NewStringUTF(className);
    assert(classNameStr != NULL);
    env->SetObjectArrayElement(strArray, 0, classNameStr);

    for (size_t i = 0; i < options.size(); ++i) {
        jstring optionsStr = env->NewStringUTF(options.itemAt(i).string());
        assert(optionsStr != NULL);
        env->SetObjectArrayElement(strArray, i + 1, optionsStr);
    }

    // 至此,strArray中包含三个成员,分别是 
    // strArray[0] = “com.android.internal.os.ZygoteInit”
    // strArray[1] = “start-system-server”
    // strArray[2] = “—abi-list=xxx”
    /*
     * 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);
    } else {
        // 找到ZygoteInit的main方法  注释①
        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 {
            // 调用ZygoteInit的main方法
            env->CallStaticVoidMethod(startClass, startMeth, strArray);

#if 0
            if (env->ExceptionCheck())
                threadExitUncaughtException(env);
#endif
        }
    }
    free(slashClassName);

    ALOGD("Shutting down VM\n");
    if (mJavaVM->DetachCurrentThread() != JNI_OK)
        ALOGW("Warning: unable to detach main thread\n");
    if (mJavaVM->DestroyJavaVM() != 0)
        ALOGW("Warning: VM did not shut down cleanly\n");
}

由于当前的运行逻辑在 Native 中,而 ZygoteInit 是用Java语言编写的,所以在 注释① 处需要使用 JNI 方式调用 ZygoteInitmain 方法,由此 Zygote 便进入了 Java 框架层,换而言之 Zygote 开创了 Java 框架层。代码如下:

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

public static void main(String argv[]) {

        ZygoteServer zygoteServer = new ZygoteServer();

        try {
            
            RuntimeInit.enableDdms();

            boolean startSystemServer = false;
            String socketName = "zygote";
            String abiList = null;
            boolean enableLazyPreload = false;

            // 解析传入的argv参数,其中argv就是AndroidRuntime.cpp中的strArray
            // strArray[0] = “com.android.internal.os.ZygoteInit”
            // strArray[1] = “start-system-server”
            // strArray[2] = “—abi-list=xxx”

            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.");
            }

            // 创建一个 Server 端的Socket,socketName的值为 “zygote”  注释①
            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();
            }

            bootTimingsTraceLog.traceBegin("PostZygoteInitGC");

            //强制执行gc进行一次垃圾回收
            gcAndFinalize();
            bootTimingsTraceLog.traceEnd(); // PostZygoteInitGC

            ...

            if (startSystemServer) {

                // 启动SystemServer进程  注释②
                Runnable r = forkSystemServer(abiList, socketName, zygoteServer);

              
                if (r != null) {
                    r.run();
                    return;
                }
            }

            // 等待 AMS 请求   注释③
            caller = zygoteServer.runSelectLoop(abiList);

        } catch (Throwable ex) {
            Log.e(TAG, "System zygote died with exception", ex);
            throw ex;
        } finally {
            zygoteServer.closeServerSocket();
        }

    
        if (caller != null) {
            caller.run();
        }
    }

注释① 处通过 registerServerSocket 方法创建一个 Server 端的 Socket ,这个 name“zygote”Socket 用于等待 ActivityManagerService 请求 Zygote 来创建新的而应用程序。在 注释② 处启动 SystemServer 进程,这样系统的服务也会由 SystemServer 进程启动起来。注释③ 调用 ZygoteServer 的 runSelectLoop 方法等待 AMS 请求创建新的应用程序进程。

上一篇下一篇

猜你喜欢

热点阅读