【Android FrameWork】Zygote

前提

1.回顾

在Android系统中,第一个启动的就是init进程,由init进程加载并解析init.rc以及init.zygote64.rc等等配置文件。来启动相应的service。Zygote就是由他启动起来的。Zygote是一个孵化器,system_server和所有的应用程序都是由他创建出来的。最初的时候Zygote进程的名称并不是Zygote而是app_process。Zygote启动后,Linux系统下的pctrl系统会调用app_process,所以把名称换成了Zygote。

2.架构

Zygote他是一个C/S架构。Zygote进程做为服务端,通过Socket的方式和其他进程进行通信。当接收到数据的时候会fork子进程,fork是不会复制父进程的内存,而是和父进程共享一个内存空间,只有需要进行内存数据修改的时候才会进行内存复制,也就是常说的读时共享,写时复制。

3.工作内容

Zygote做为一个孵化器,会提前加载一些系统资源、创建Java虚拟机、注册JNI等等,这样子进程就可以直接使用,避免重复加载。比如Zygote中的JNI函数、主题资源等等。

正文

1.Zygote的启动

在之前的init中有讲到,init解析init.rc的时候会解析service字段 并添加到serviceList中,并且执行fork对应的进程,执行程序。这些启动脚本都存放在 system/core/rootdir目录中。

代码如下:

#解析服务 并且添加到serviceList中
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
    socket usap_pool_primary 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
    
#遍历serviceList 调用start函数 fork进程 execv执行app_process64
on nonencrypted class_start main class_start late_start
    

app_process64对应代码就在/frameworks/base/cmds/app_process目录下。对应的源文件就是app_main.cpp。
init进程启动后通过调用execv(“/system/bin/app_process64”,“-Xzygote /system/bin --zygote --start-system-server”) 执行程序,并且将参数传递给main函数。

接下来我们看看zygote的main函数做了什么?

//init传递过来的参数如下 -Xzygote /system/bin --zygote --start-system-server
int main(int argc, char* const argv[])
{
    //#ifndef LOG_NDEBUG
    //#ifdef NDEBUG
    //#define LOG_NDEBUG 1
    //#else
    //#define LOG_NDEBUG 0  所以这里是true 会把参数存放到argv_String中,然后打印出来
    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,并将参数传递给AppRuntime
    AppRuntime runtime(argv[0], computeArgBlockSize(argc, argv));
    argc--;
    argv++;
    bool known_command = false;

    int i;
    for (i = 0; i < argc; i++) {
        if (known_command == true) {
          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) {
            known_command = true;
            ALOGV("app_process main found known command '%s'", argv[i]);
          }
        }

        if (argv[i][0] != '-') {//如果参数第一个字符是'-'跳出循环,Zygote传递的第一个参数是-Xzygote 所以执行到这里会跳出循环
            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;  
    while (i < argc) {
        const char* arg = argv[i++];
        if (strcmp(arg, "--zygote") == 0) {//传递的参数有--zygote的就把zygote赋值为true niceName = zygote
            zygote = true;
            niceName = ZYGOTE_NICE_NAME;
        } else if (strcmp(arg, "--start-system-server") == 0) { //传递的参数有start--system-server 把startSystemServer 赋值为tue表示当前进程的main是需要开启system_server的
            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程序传递过来的className 也就是需要启动的class
            className.setTo(arg);
            break;
        } else {
            --i;
            break;
        }
    }

    Vector<String8> args;
    if (!className.isEmpty()) {//如果class不为空 说明是application,但是此时我们是空的,所以我们会走下面的分支
        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 {//这里就是zygote启动模式
        // We're in zygote mode.
        maybeCreateDalvikCache();//创建Dalvik的缓存目录, data/dalvik-cache的目录

        if (startSystemServer) {//如果需要运行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);

        for (; i < argc; ++i) {
            args.add(String8(argv[i]));
        }
    }

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

    if (zygote) {//注意这里之前传递的参数zygote 所以这里是true。他会调用runtime的start函数 传递com.android.internal.os.ZygoteInit 以及 init传递过来的参数 和true
        runtime.start("com.android.internal.os.ZygoteInit", args, zygote);
    } else if (className) {//application模式
        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.");
    }
}

代码比较长,我总结下首先会打印日志把传递过来的参数打印出来。接着会创建AppRuntime对象,将参数传递给AppRuntime并初始化。接着根据init传递过来的参数--zygotezygote设置成true表示是以zygote模式启动,如果需要开启system_server的会把start-system-server 也设置为true。如果传递的是application就是以app模式启动,他就会查找对应的className,如果className部位空就会添加对应的参数。否则就是Zygote模式,在Zygote模式中会先创建Davik的缓存目录。最后调用runtime.start(),看是以什么模式启动,如果是Zygote模式启动就会传递com.android.internal.os.ZygoteInit和将整理的参数以及zygote 传递下去,如果是app模式就会传递com.android.internal.os.RuntimeInit和 args以及 zygote;

2.AndroidRuntime

接下来我们需要接触两个非常重要的类AppRuntime和AndroidRuntime。这两个类是整个Android Runtime环境的接口类,
他们的关系是:

class AppRuntime : public AndroidRuntime

AppRuntime是AndroidRuntime的子类。

看看AppRuntime::start()

image.png
我们看到AppRuntime没有start函数,start函数的实现在父类AndroidRuntime中。我们直接跳到AndroidRuntime中看看。
文件目录:/framework/base/core/jni/AndroidRuntime


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

    //获取ANDROID_ROOT 目录
    const char* rootDir = getenv("ANDROID_ROOT");
    if (rootDir == NULL) {
        rootDir =
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值