android8.1系统启动过程(五) zygote进程分析1

事先声明本文为作者本人记录学习使用

其中部分文字或者技术观点摘自https://blog.csdn.net/marshal_zsx/article/details/80547780  这里推荐此作者文章


zygote进程主要负责

                               创建Java虚拟机,

                               加载系统资源,

                               启动SystemServer进程,

                               以及在后续运行过程中启动普通的应用程序


init.rc  AOSP/system/core/rootdir/init.rc

//部分代码截取
...
import /init.${ro.hardware}.rc
import /vendor/etc/init/hw/init.${ro.hardware}.rc
import /init.usb.configfs.rc
import /init.${ro.zygote}.rc
 
on early-init
    # Set init and its forked children's oom_adj.
    write /proc/1/oom_score_adj -1000
...

这里的  import /init.${ro.zygote}.rc  导入的就是  init.zygote64.rc


init.zygote64.rc  AOSP/system/core/rootdir/init.zygote64.rc

    进程名称是zygote,运行的二进制文件在/system/bin/app_process64  启动参数是 -Xzygote /system/bin --zygote --start-system-server

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

main(int argc, char** argv)  AOSP/system/core/rootdir/init.cpp

    在init进程的最后,会加入 late-init 的trigger

...
if (bootmode == "charger") {
    am.QueueEventTrigger("charger");
} else {
    am.QueueEventTrigger("late-init");
}
...

init.rc  AOSP/system/core/rootdir/init.rc

    而当  on late-init  触发时会触发trigger zygote-start

on late-init
...
    # Now we can start zygote for devices with file based encryption
    trigger zygote-start
...

当zygote-start 触发时,会执行以下操作

on zygote-start && property:ro.crypto.state=unencrypted
    # A/B update verifier that marks a successful boot.
    exec_start update_verifier_nonencrypted
    start netd
    start zygote
    start zygote_secondary

on zygote-start && property:ro.crypto.state=unsupported
    # A/B update verifier that marks a successful boot.
    exec_start update_verifier_nonencrypted
    start netd
    start zygote
    start zygote_secondary

on zygote-start && property:ro.crypto.state=encrypted && property:ro.crypto.type=file
    # A/B update verifier that marks a successful boot.
    exec_start update_verifier_nonencrypted
    start netd
    start zygote
    start zygote_secondary

builtin_functions  AOSP/system/core/init/builtins.cpp

    start 命令有一个对应的执行函数 do_start

static const Map builtin_functions = {
        ...
        {"setrlimit",               {3,     3,    do_setrlimit}},
        {"start",                   {1,     1,    do_start}},
        {"stop",                    {1,     1,    do_stop}},
        ...
    };

do_start首先是通过FindServiceByName去service数组中遍历,根据名字匹配出对应的service,然后调用service的Start函数,Start函数我们在上一篇结尾有分析,主要是fork出一个新进程然后执行service对应的二进制文件,并将参数传递进去.

static int do_start(const std::vector<std::string>& args) {
    Service* svc = ServiceManager::GetInstance().FindServiceByName(args[1]);//找出对应service
    if (!svc) {
        LOG(ERROR) << "do_start: Service " << args[1] << " not found";
        return -1;
    }
    if (!svc->Start())  //调用start
        return -1;
    return 0;
}

Android.mk  AOSP/frameworks/base/cmds/app_process/Android.mk

    zygote对应的二进制文件是 /system/bin/app_process64 ,app_process、app_process32、app_process64,对应的源文件都是app_main.cpp.

app_process_src_files := \
    app_main.cpp \
...
LOCAL_MODULE:= app_process
LOCAL_MULTILIB := both
LOCAL_MODULE_STEM_32 := app_process32
LOCAL_MODULE_STEM_64 := app_process64

main()   AOSP/frameworks/base/cmds/app_process/app_main.cpp 

int main(int argc, char* const argv[])
{
    //将参数argv放到argv_String字符串中,然后打印出来
    //之前start zygote传入的参数是 -Xzygote /system/bin --zygote --start-system-server --socket-name=zygote
    if (!LOG_NDEBUG) {
      String8 argv_String;
      for (int i = 0; i < argc; ++i) {
        argv_String.append("\"");
        argv_String.append(argv[i]);
        argv_String.append("\" ");
      }
      ALOGV("app_process main with argv: %s", argv_String.string());
    }

    AppRuntime runtime(argv[0], computeArgBlockSize(argc, argv));//构建AppRuntime对象,并将参数传入
    // Process command line arguments
    // ignore argv[0]
    argc--;
    argv++;

    // Everything up to '--' or first non '-' arg goes to the vm.
    //
    // The first argument after the VM args is the "parent dir", which
    // is currently unused.
    //
    // After the parent dir, we expect one or more the following internal
    // arguments :
    //
    // --zygote : Start in zygote mode
    // --start-system-server : Start the system server.
    // --application : Start in application (stand alone, non zygote) mode.
    // --nice-name : The nice name for this process.
    //
    // For non zygote starts, these arguments will be followed by
    // the main class name. All remaining arguments are passed to
    // the main method of this class.
    //
    // For zygote starts, all remaining arguments are passed to the zygote.
    // main function.
    //
    // Note that we must copy argument string values since we will rewrite the
    // entire argument block when we apply the nice name to argv0.
    //
    // As an exception to the above rule, anything in "spaced commands"
    // goes to the vm even though it has a space in it.

    //上面这段英文大概讲的是,所有在 "--" 后面的非 "-"开头的参数都将传入vm, 但是有个例外是spaced commands数组中的参数

    const char* spaced_commands[] = { "-cp", "-classpath" };//这两个参数是Java程序需要依赖的Jar包,相当于import
    // Allow "spaced commands" to be succeeded by exactly 1 argument (regardless of -s).
    bool known_command = false;
    int i;
    for (i = 0; i < argc; i++) {
        if (known_command == true) { //将spaced_commands中的参数额外加入VM
          runtime.addOption(strdup(argv[i]));
          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) {//比较参数是否是spaced_commands中的参数
            known_command = true;
            ALOGV("app_process main found known command '%s'", argv[i]);
          }
        }

        if (argv[i][0] != '-') { //如果参数第一个字符是'-',直接跳出循环,之前传入的第一个参数是 -Xzygote,所以执行到这儿就跳出了,i=0
            break;
        }
        if (argv[i][1] == '-' && argv[i][2] == 0) {
            ++i; // Skip --.
            break;
        }

        runtime.addOption(strdup(argv[i]));
        ALOGV("app_process main add option '%s'", argv[i]);
    }

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

    ++i;  // Skip unused "parent dir" argument.
    //跳过一个参数,之前跳过了-Xzygote,这里继续跳过 /system/bin ,也就是所谓的 "parent dir"
    while (i < argc) {
        const char* arg = argv[i++];
        if (strcmp(arg, "--zygote") == 0) {//表示是zygote启动模式
            zygote = true;
            niceName = ZYGOTE_NICE_NAME;//这个值根据平台可能是zygote64或zygote
        } else if (strcmp(arg, "--start-system-server") == 0) {//需要启动SystemServer
            startSystemServer = true;
        } else if (strcmp(arg, "--application") == 0) {//表示是application启动模式,也就是普通应用程序
            application = true;
        } else if (strncmp(arg, "--nice-name=", 12) == 0) {//进程别名
            niceName.setTo(arg + 12);
        } else if (strncmp(arg, "--", 2) != 0) {//application启动的class
            className.setTo(arg);
            break;
        } else {
            --i;
            break;
        }
    }

    Vector<String8> args;
    if (!className.isEmpty()) {//className不为空,说明是application启动模式
        args.add(application ? String8("application") : String8("tool"));
        runtime.setClassNameAndArgs(className, argc - i, argv + i);//将className和参数设置给runtime

        if (!LOG_NDEBUG) {//打印class带的参数
          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 { //zygote启动模式
        // We're in zygote mode.
        maybeCreateDalvikCache(); //新建Dalvik的缓存目录

        if (startSystemServer) {//加入start-system-server参数
            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); //加入--abi-list=参数

        // In zygote mode, pass all remaining arguments to the zygote
        // main() method.
        for (; i < argc; ++i) {//将剩下的参数加入args
            args.add(String8(argv[i]));
        }
    }

    if (!niceName.isEmpty()) {//设置进程别名
        runtime.setArgv0(niceName.string(), true /* setProcName */);
    }

    if (zygote) { //如果是zygote启动模式,则加载ZygoteInit
        runtime.start("com.android.internal.os.ZygoteInit", args, zygote);
    } else if (className) {//如果是application启动模式,则加载RuntimeInit
        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.");
    }
}

最后调用的是runtime.start函数,这个就是要启动虚拟机了,接下来我们分析start函数

AppRuntime runtime(argv[0], computeArgBlockSize(argc, argv));  首先在AppRuntime中寻找是否存在start函数如果没有就在其父类AndroidRuntime中寻找  (class AppRuntime : public AndroidRuntime)


start()  AOSP/frameworks/base/core/jni/AndroidRuntime.cpp    看注释

void AndroidRuntime::start(const char* className, const Vector<String8>& options, bool zygote)
{
    ...
    JniInvocation jni_invocation;
    jni_invocation.Init(NULL);
    JNIEnv* env;
    if (startVm(&mJavaVM, &env, zygote) != 0) {  //创建java虚拟机
        return;
    }
    onVmCreated(env);

    /*
     * Register android functions.  
     */
    if (startReg(env) < 0) {  //为java虚拟机注册jni方法
        ALOGE("Unable to register all android natives\n");
        return;
    }

    /*
     * We want to call main() with a String array with arguments in it.
     * At present we have two arguments, the class name and an option string.
     * Create an array to hold them.
     */
    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);
    //className 为  com.android.internal.os.ZygoteInit
    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);
    }

    /*
     * Start VM.  This thread becomes the main thread of the VM, and will
     * not return until the VM exits.
     */
    //com.android.internal.os.ZygoteInit  把“.”替换为“/”
    char* slashClassName = toSlashClassName(className != NULL ? className : "");
    //找到ZygoteInit
    jclass startClass = env->FindClass(slashClassName);
    if (startClass == NULL) {
        ALOGE("JavaVM unable to locate class '%s'\n", slashClassName);
        /* keep going */
    } 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 {
            //调用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");
}

由此又c++层调用到了java层


main()  AOSP/frameworks/base/core/java/com/android/internal/os/ZygoteInit.java

public static void main(String argv[]) {
        ZygoteServer zygoteServer = new ZygoteServer();
        ...
            zygoteServer.registerServerSocket(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) {
                ...
                preload(bootTimingsTraceLog);
                ...
            } else {
                Zygote.resetNicePriority();
            }
           ...
            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();
        }
    }

    【1】创建server端的socket这个名为zygote的Socket用于等待AMS请求zygote来创建新的应用程序进程

zygoteServer.registerServerSocket(socketName);

    【2】预加载类和资源

preload(bootTimingsTraceLog);

    【3】启动systemserver进程  系统的服务也将由systemserver启动起来

if (startSystemServer) {
   Runnable r = forkSystemServer(abiList, socketName, zygoteServer);
   if (r != null) {
       r.run();
       return;
   }
}

     【4】启动等待ams创建新的进程

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

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值