Android 8.1 源码_启动篇(二) -- 深入研究 zygote (2)

定义了service,肯定有地方调用 start zygote。在之前init解析的博客中,我们分析过init进程的启动。init进程启动的最后,会产生”late-init”事件。

// Don't mount filesystems or start core system services in charger mode. std::string bootmode = GetProperty("ro.bootmode", ""); if (bootmode == "charger") { am.QueueEventTrigger("charger"); } else { am.QueueEventTrigger("late-init"); }

对应于init.rc配置文件中,我们找到如下代码:

# Mount filesystems and start core system services. on late-init trigger early-fs ... ... # Now we can start zygote for devices with file based encryption trigger zygote-start // 触发了zygote-start事件后,就会启动zygote进程 ... ...

对应于init.rc配置文件中,我们找到如下代码:

# It is recommended to put unnecessary data/ initialization from post-fs-data # to start-zygote in device's init.rc to unblock 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对应的映射关系定义于system/core/init/builtins.cpp中 start zygote // 调用start对应的处理函数,启动名为zygote的服务(传入前文init.zygote.rc中定义的参数) 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

start命令有一个对应的执行函数do_start,定义在platform/system/core/init/builtins.cpp中

const BuiltinFunctionMap::Map& BuiltinFunctionMap::map() const { constexpr std::size_t kMax = std::numeric_limits<std::size_t>::max(); // clang-format off static const Map builtin_functions = { ... ... {"start", {1, 1, do_start}}, ... ... }; // clang-format on return builtin_functions; }

我们来看下do_start():

static int do_start(const std::vector<std::string>& args) { Service* svc = ServiceManager::GetInstance().FindServiceByName(args[1]); // 找到zygote service对应信息 if (!svc) { LOG(ERROR) << "do_start: Service " << args[1] << " not found"; return -1; } if (!svc->Start()) // 启动对应的进程 return -1; return 0; }

do_start首先是通过FindServiceByName去service数组中遍历,根据名字匹配出对应的service,然后调用service的Start函数。

最后,我们来看看service.cpp中定义Start函数:

bool Service::Start() { ... ... pid_t pid = -1; if (namespace_flags_) { pid = clone(nullptr, nullptr, namespace_flags_ | SIGCHLD, nullptr); } else { pid = fork(); // 从init进程中,fork出zygote进程 } ... ... }

Start函数主要是fork出一个新进程,然后执行service对应的二进制文件,并将参数传递进去。那么下面我们以init.zygote64.rc为例进行分析。

app_process

从上面我们分析的init.zygote64.rc可以看出,zygote64启动文件的地址为app_process64。app_process64对应的代码定义在frameworks/base/cmds/app_process中,

我们来看看对应的Android.mk: frameworks/base/cmds/app_process

LOCAL_PATH:= $(call my-dir) ... ... 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

其实不管是app_process、app_process32还是app_process64,对应的源文件都是app_main.cpp。

接下来我们就看看app_process对应的main函数,该函数定义于app_main.cpp中。

在app_main.cpp的main函数中,主要做的事情就是参数解析. 这个函数有两种启动模式:

      ✨ 一种是zygote模式,也就是初始化zygote进程,传递的参数有--start-system-server --socket-name=zygote,前者表示启动SystemServer,后者指定socket的名称(Zygote64_32)。
      ✨ 一种是application模式,也就是启动普通应用程序,传递的参数有class名字以及class带的参数。

两者最终都是调用AppRuntime对象的start函数,加载ZygoteInit或RuntimeInit两个Java类,并将之前整理的参数传入进去。

我们这里暂时只讲解ZygoteInit的加载流程。

int main(int argc, char* const argv[]) { // 将参数argv放到argv_String字符串中,然后打印出来 // 之前start zygote传入的参数是 -Xzygote /system/bin --zygote --start-system-server 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定义于app_main.cpp中,继承自AndroidRuntime // 就是对Android运行环境的一种抽象,类似于java虚拟机对Java程序的作用 AppRuntime runtime(argv[0], computeArgBlockSize(argc, argv)); // Process command line arguments // ignore argv[0] argc--; argv++; // 这两个参数是Java程序需要依赖的Jar包,相当于import const char* spaced_commands[] = { "-cp", "-classpath" }; // 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++) { // 将spaced_commands中的参数额外加入VM 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) { // 比较参数是否是spaced_commands中的参数 if (strcmp(argv[i], spaced_commands[j]) == 0) { known_command = true; ALOGV("app_process main found known command '%s'", argv[i]); } } // 如果参数第一个字符是'-',直接跳出循环,之前传入的第一个参数是 -Xzygote,所以执行到这儿就跳出了 if (argv[i][0] != '-') { break; } if (argv[i][1] == '-' && argv[i][2] == 0) { ++i; // Skip --. break; } 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 option '%s'", argv[i]); } // Parse runtime arguments. Stop at first unrecognized option. // 从这里其实可以看出,通过app_main可以启动zygote、system-server及普通apk进程 // 这个可以通过init.rc来配置 bool zygote = false; bool startSystemServer = false; bool application = false; String8 niceName; // app_process的名称改为zygote String8 className; // 启动apk进程时,对应的类名 ++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) { startSystemServer = true; // init.zygote.rc中定义了该字段,启动zygote后会启动system-server } else if (strcmp(arg, "--application") == 0) { application = true; // 表示是application启动模式,也就是普通应用程序 } else if (strncmp(arg, "--nice-name=", 12) == 0) { niceName.setTo(arg + 12); // 进程别名,可以自己指定进程名 } else if (strncmp(arg, "--", 2) != 0) { className.setTo(arg); // 与--application配置,启动指定的类,application启动的class break; } else { --i; break; } } // 准备参数 Vector<String8> args; if (!className.isEmpty()) { // className不为空,说明是application启动模式 // 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); // 将className和参数设置给runtime ... ... } else { // zygote启动模式 // We're in zygote mode. maybeCreateDalvikCache(); // 创建Dalvik的缓存目录并定义权限 if (startSystemServer) { // 增加start-system-server参数,默认启动zygote后,就会启动system_server args.add(String8("start-system-server")); } char prop[PROP_VALUE_MAX]; // 获取平台对应的abi信息 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="); // 参数需要制定abi 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.add(String8(argv[i])); // 将剩下的参数加入args } } if (!niceName.isEmpty()) { // 将app_process的进程名,替换为niceName runtime.setArgv0(niceName.string(), true /* setProcName */); } if (zygote) { // 调用Runtime的start函数, 启动ZygoteInit runtime.start("com.android.internal.os.ZygoteInit", args, zygote); } else if (className) { // 启动zygote没有进入这个分支 // 但这个分支说明,通过配置init.rc文件,其实是可以不通过zygote来启动一个进程 // 如果是application启动模式,则加载RuntimeInit runtime.start("com.android.internal.os.RuntimeInit", args, zygote); } else { // error情况 fprintf(stderr, "Error: no class name or --zygote supplied.\n"); app_usage(); LOG_ALWAYS_FATAL("app_process: no class name or --zygote supplied."); } } AndroidRuntime

由于AppRuntime继承自AndroidRuntime,且没有重写start方法,因此zygote的流程进入到了AndroidRuntime.cpp。

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zygdyw.html