static noinline void __ref rest_init(void) { ... /* * We need to spawn init first so that it obtains pid 1, however * the init task will end up wanting to create kthreads, which, if * we schedule it before we create kthreadd, will OOPS. */ pid = kernel_thread(kernel_init, NULL, CLONE_FS); ... }
staticint __ref kernel_init(void *unused) { int ret; kernel_init_freeable(); /* need to finish all async __init code before freeing the memory */ async_synchronize_full(); ftrace_free_init_mem(); free_initmem(); mark_readonly(); system_state = SYSTEM_RUNNING; numa_default_policy(); rcu_end_inkernel_boot(); place_marker("M - DRIVER Kernel Boot Done"); if (ramdisk_execute_command) { ret = run_init_process(ramdisk_execute_command); if (!ret) return0; pr_err("Failed to execute %s (error %d)\n", ramdisk_execute_command, ret); } /* * We try each of these until one succeeds. * * The Bourne shell can be used instead of init if we are * trying to recover a really broken machine. */ if (execute_command) { ret = run_init_process(execute_command); if (!ret) return0; panic("Requested init %s failed (error %d).", execute_command, ret); } // ramdisk_execute_command 和 execute_command 定义的程序没找到,则从如下目录寻找 init 进行启动 if (!try_to_run_init_process("/sbin/init") || !try_to_run_init_process("/etc/init") || !try_to_run_init_process("/bin/init") || !try_to_run_init_process("/bin/sh")) // try_to_run_init_process 最终也是调用 run_init_process 函数 return0; panic("No working init found. Try passing init= option to kernel. " "See Linux Documentation/admin-guide/init.rst for guidance."); }
// This is needed for log wrapper, which gets called before ueventd runs. CHECKCALL(mknod("/dev/ptmx", S_IFCHR | 0666, makedev(5, 2))); CHECKCALL(mknod("/dev/null", S_IFCHR | 0666, makedev(1, 3)));
// These below mounts are done in first stage init so that first stage mount can mount // subdirectories of /mnt/{vendor,product}/. Other mounts, not required by first stage mount, // should be done in rc files. // Mount staging areas for devices managed by vold // See storage config details at http://source.android.com/devices/storage/ CHECKCALL(mount("tmpfs", "/mnt", "tmpfs", MS_NOEXEC | MS_NOSUID | MS_NODEV, "mode=0755,uid=0,gid=1000")); // /mnt/vendor is used to mount vendor-specific partitions that can not be // part of the vendor partition, e.g. because they are mounted read-write. CHECKCALL(mkdir("/mnt/vendor", 0755)); // 创建 vendor 目录 // /mnt/product is used to mount product-specific partitions that can not be // part of the product partition, e.g. because they are mounted read-write. CHECKCALL(mkdir("/mnt/product", 0755)); // 创建 product 目录
// /debug_ramdisk is used to preserve additional files from the debug ramdisk CHECKCALL(mount("tmpfs", "/debug_ramdisk", "tmpfs", MS_NOEXEC | MS_NOSUID | MS_NODEV, "mode=0755,uid=0,gid=0")); #undef CHECKCALL
SetStdioToDevNull(argv); // 把标准输入、标准输出和标准错误重定向到空设备文件 "/dev/null" // Now that tmpfs is mounted on /dev and we have /dev/kmsg, we can actually // talk to the outside world... InitKernelLogging(argv); // 初始化 kernel log 系统
...
LOG(INFO) << "init first stage started!";
...
if (!DoFirstStageMount()) { // DoFirstStageMount:初始化特定设备并挂载 LOG(FATAL) << "Failed to mount required partitions early ..."; }
// execv() only returns if an error happened, in which case we // panic and never fall through this conditional. PLOG(FATAL) << "execv(\"" << path << "\") failed";
// Set up SELinux, loading the SELinux policy. // 初始化 SELinux,加载 SELinux 策略,配置 log 输出 SelinuxSetupKernelLogging(); SelinuxInitialize();
// We're in the kernel domain and want to transition to the init domain. File systems that // store SELabels in their xattrs, such as ext4 do not need an explicit restorecon here, // but other file systems do. In particular, this is needed for ramdisks such as the // recovery image for A/B devices. if (selinux_android_restorecon("/system/bin/init", 0) == -1) { PLOG(FATAL) << "restorecon failed of /system/bin/init failed"; }
// execv() only returns if an error happened, in which case we // panic and never return from this function. PLOG(FATAL) << "execv(\"" << path << "\") failed";
voidPropertyInit(){ selinux_callback cb; cb.func_audit = PropertyAuditCallback; // selinux 控制属性的 set 和 get selinux_set_callback(SELINUX_CB_AUDIT, cb);
mkdir("/dev/__properties__", S_IRWXU | S_IXGRP | S_IXOTH); CreateSerializedPropertyInfo(); // 从文件中加载属性值 // 初始化 __system_property_area 属性内存区域,将 /dev/__properties__/property_info 设备文件映射到共享内存,此区域记录着所有的属性值 if (__system_property_area_init()) { LOG(FATAL) << "Failed to initialize property area"; } if (!property_info_area.LoadDefaultPath()) { LOG(FATAL) << "Failed to load serialized property info file"; }
// If arguments are passed both on the command line and in DT, // properties set in DT always have priority over the command-line ones. // 读取设备树 /proc/device-tree/firmware/android/ 中的 name 和 compatible 节点内容,添加 ro.boot. 前缀后加入到 property 属性系统中 ProcessKernelDt(); // 读取 /pro/cmdline,将 androidboot. 开头的变量,添加 ro.boot. 前缀后加入到 property 属性系统中 ProcessKernelCmdline();
// Propagate the kernel variables to internal variables // used by init as well as the current required properties. ExportKernelBootProps(); // 处理一些特定的属性值,如果没有赋值,则将其赋值为 nuknown 或者 0
voidCreateSerializedPropertyInfo(){ auto property_infos = std::vector<PropertyInfoEntry>(); if (access("/system/etc/selinux/plat_property_contexts", R_OK) != -1) { if (!LoadPropertyInfoFromFile("/system/etc/selinux/plat_property_contexts", &property_infos)) { return; } // Don't check for failure here, so we always have a sane list of properties. // E.g. In case of recovery, the vendor partition will not have mounted and we // still need the system / platform properties to function. if (access("/system_ext/etc/selinux/system_ext_property_contexts", R_OK) != -1) { LoadPropertyInfoFromFile("/system_ext/etc/selinux/system_ext_property_contexts", &property_infos); } if (!LoadPropertyInfoFromFile("/vendor/etc/selinux/vendor_property_contexts", &property_infos)) { // Fallback to nonplat_* if vendor_* doesn't exist. LoadPropertyInfoFromFile("/vendor/etc/selinux/nonplat_property_contexts", &property_infos); } if (access("/product/etc/selinux/product_property_contexts", R_OK) != -1) { LoadPropertyInfoFromFile("/product/etc/selinux/product_property_contexts", &property_infos); } if (access("/odm/etc/selinux/odm_property_contexts", R_OK) != -1) { LoadPropertyInfoFromFile("/odm/etc/selinux/odm_property_contexts", &property_infos); } } else { if (!LoadPropertyInfoFromFile("/plat_property_contexts", &property_infos)) { return; } LoadPropertyInfoFromFile("/system_ext_property_contexts", &property_infos); if (!LoadPropertyInfoFromFile("/vendor_property_contexts", &property_infos)) { // Fallback to nonplat_* if vendor_* doesn't exist. LoadPropertyInfoFromFile("/nonplat_property_contexts", &property_infos); } LoadPropertyInfoFromFile("/product_property_contexts", &property_infos); LoadPropertyInfoFromFile("/odm_property_contexts", &property_infos); }
voidPropertyLoadBootDefaults(){ // TODO(b/117892318): merge prop.default and build.prop files into one // We read the properties and their values into a map, in order to always allow properties // loaded in the later property files to override the properties in loaded in the earlier // property files, regardless of if they are "ro." properties or not. std::map<std::string, std::string> properties; if (!load_properties_from_file("/system/etc/prop.default", nullptr, &properties)) { // Try recovery path if (!load_properties_from_file("/prop.default", nullptr, &properties)) { // Try legacy path load_properties_from_file("/default.prop", nullptr, &properties); } } load_properties_from_file("/system/build.prop", nullptr, &properties); load_properties_from_file("/system_ext/build.prop", nullptr, &properties); load_properties_from_file("/vendor/default.prop", nullptr, &properties); load_properties_from_file("/vendor/build.prop", nullptr, &properties); if (SelinuxGetVendorAndroidVersion() >= __ANDROID_API_Q__) { load_properties_from_file("/odm/etc/build.prop", nullptr, &properties); } else { load_properties_from_file("/odm/default.prop", nullptr, &properties); load_properties_from_file("/odm/build.prop", nullptr, &properties); } load_properties_from_file("/product/build.prop", nullptr, &properties); load_properties_from_file("/factory/factory.prop", "ro.*", &properties); ... for (constauto& [name, value] : properties) { std::string error; if (PropertySet(name, value, &error) != PROP_SUCCESS) { LOG(ERROR) << "Could not set '" << name << "' to '" << value << "' while loading .prop files" << error; } }
// 处理 "sys.powerctl" 开头的属性 // sys.powerctl is a special property that is used to make the device reboot. We want to log // any process that sets this property to be able to accurately blame the cause of a shutdown. if (name == "sys.powerctl") { std::string cmdline_path = StringPrintf("proc/%d/cmdline", cr.pid); std::string process_cmdline; std::string process_log_string; if (ReadFileToString(cmdline_path, &process_cmdline)) { // Since cmdline is null deliminated, .c_str() conveniently gives us just the process // path. process_log_string = StringPrintf(" (%s)", process_cmdline.c_str()); } LOG(INFO) << "Received sys.powerctl='" << value << "' from pid: " << cr.pid << process_log_string; if (value == "reboot,userspace" && !is_userspace_reboot_supported().value_or(false)) { *error = "Userspace reboot is not supported by this device"; return PROP_ERROR_INVALID_VALUE; } }
std::string bootscript = GetProperty("ro.boot.init_rc", ""); if (bootscript.empty()) { // 如果 ro.boot.init_rc 属性没有定义,则解析 /system/etc/init/hw/init.rc 和 // system, system_ext, product, odm, vender/etc/init 目录下的 .rc 文件 parser.ParseConfig("/system/etc/init/hw/init.rc"); if (!parser.ParseConfig("/system/etc/init")) { late_import_paths.emplace_back("/system/etc/init"); } // late_import is available only in Q and earlier release. As we don't // have system_ext in those versions, skip late_import for system_ext. parser.ParseConfig("/system_ext/etc/init"); if (!parser.ParseConfig("/product/etc/init")) { late_import_paths.emplace_back("/product/etc/init"); } if (!parser.ParseConfig("/odm/etc/init")) { late_import_paths.emplace_back("/odm/etc/init"); } if (!parser.ParseConfig("/vendor/etc/init")) { late_import_paths.emplace_back("/vendor/etc/init"); } } else { parser.ParseConfig(bootscript); } }
// If we encounter a bad section start, there is no valid parser object to parse the subsequent // sections, so we must suppress errors until the next valid section is found. bool bad_section_found = false; ... for (;;) { switch (next_token(&state)) { case T_EOF: // EOF: End Of File,即解析完成到末端了, end_section();
for (constauto& [section_name, section_parser] : section_parsers_) { section_parser->EndFile(); }
return; case T_NEWLINE: { state.line++; if (args.empty()) break; // If we have a line matching a prefix we recognize, call its callback and unset any // current section parsers. This is meant for /sys/ and /dev/ line entries for // uevent. auto line_callback = std::find_if( line_callbacks_.begin(), line_callbacks_.end(), [&args](constauto& c) { return android::base::StartsWith(args[0], c.first); }); if (line_callback != line_callbacks_.end()) { end_section(); ... } elseif (section_parsers_.count(args[0])) { end_section(); section_parser = section_parsers_[args[0]].get(); section_start_line = state.line; if (auto result = section_parser->ParseSection(std::move(args), filename, state.line); !result.ok()) { ... } } elseif (section_parser) { if (auto result = section_parser->ParseLineSection(std::move(args), state.line); !result.ok()) { ... } } elseif (!bad_section_found) { ... } args.clear(); break; } case T_TEXT: args.emplace_back(state.text); break; } } }
intSecondStageMain(int argc, char** argv){ ... while (true) { // By default, sleep until something happens. // epoll 系统轮询等待消息处理 auto epoll_timeout = std::optional<std::chrono::milliseconds>{}; // epoll 的阻塞时间
auto shutdown_command = shutdown_state.CheckShutdown(); if (shutdown_command) { HandlePowerctlMessage(*shutdown_command); }
if (!(prop_waiter_state.MightBeWaiting() || Service::is_exec_service_running())) { am.ExecuteOneCommand(); // 执行一个 command } if (!IsShuttingDown()) { auto next_process_action_time = HandleProcessActions();
// If there's a process that needs restarting, wake up in time for that. // 如果有需要重新启动的进程,epoll_timeout 设置为重启等待时间 if (next_process_action_time) { epoll_timeout = std::chrono::ceil<std::chrono::milliseconds>( *next_process_action_time - boot_clock::now()); if (*epoll_timeout < 0ms) epoll_timeout = 0ms; } }
if (!(prop_waiter_state.MightBeWaiting() || Service::is_exec_service_running())) { // If there's more work to do, wake up again immediately. if (am.HasMoreCommands()) epoll_timeout = 0ms; }
auto pending_functions = epoll.Wait(epoll_timeout); if (!pending_functions.ok()) { LOG(ERROR) << pending_functions.error(); } elseif (!pending_functions->empty()) { // We always reap children before responding to the other pending functions. This is to // prevent a race where other daemons see that a service has exited and ask init to // start it again via ctl.start before init has reaped it. ReapAnyOutstandingChildren(); for (constauto& function : *pending_functions) { (*function)(); } } if (!IsShuttingDown()) { HandleControlMessages(); SetUsbController(); } }
// If this was the last command in the current action, then remove // the action from the executing list. // If this action was oneshot, then also remove it from actions_. ++current_command_; // current_command_ 加 1 // 加 1 后 current_command 等于 action 的 command 条数,即上面执行的 current_command 是此 action 中的最后一条 command if (current_command_ == action->NumCommands()) { current_executing_actions_.pop(); // 移除 current_executing_actions_ 中的 action current_command_ = 0; // 如果 action 只执行一次,则把此 action 从 actions_ 中移除 if (action->oneshot()) { auto eraser = [&action](std::unique_ptr<Action>& a) { return a.get() == action; }; actions_.erase(std::remove_if(actions_.begin(), actions_.end(), eraser), actions_.end()); } } }