在帕美尔省后面有一座金刚山,它有一小时路程高,一小时路程宽,一小时路程深。有一只鸟每隔一百年飞到这里来一次,在这座山上磨一磨它的小嘴。要等到这座山完全磨平,那么永恒的第一秒钟才算过去。 ----------- 坚持


Android操作系统已经成为全球最重要的操作系统,系统的开放性为他的发展带来了无数的可能性,由Android系统衍生出来的物联网系统AndroidThings简化了嵌入式设备开发的难度,专为低端用户服务的AndroidGo进一步开拓了低端用户市场,随着Android系统的不断发展完善,迎来更好的用户体验;同时Kotlin , 即时应用的新技术使得Android越发得老当益壮。不得不说对于Google即将推出的Fuchsia(灯笼海棠系统)目前来说不足也为惧,它对Android应用的支持也为新一代中端系统提供了过渡的空间; 技术是为了提供更好的服务而发展出的手段;

1.系统孵化准备第一阶段

int main(int argc, char** argv) {if (!strcmp(basename(argv[0]), "ueventd")) {return ueventd_main(argc, argv); //1.1uevent message 监听}if (!strcmp(basename(argv[0]), "watchdogd")) {return watchdogd_main(argc, argv); //1.2系统看门狗设置}if (REBOOT_BOOTLOADER_ON_PANIC) {InstallRebootSignalHandlers(); //设置系统重启Signal Action}add_environment("PATH", _PATH_DEFPATH); //注册环境PATHbool is_first_stage = (getenv("INIT_SECOND_STAGE") == nullptr); //检查环境变量if (is_first_stage) {boot_clock::time_point start_time = boot_clock::now();// Clear the umask.umask(0); //清空文件权限// Get the basic filesystem setup we need put together in the initramdisk// on / and then we'll let the rc file figure out the rest.//挂在文件系统,创建文件并设置文件权限mount("tmpfs", "/dev", "tmpfs", MS_NOSUID, "mode=0755");mkdir("/dev/pts", 0755);mkdir("/dev/socket", 0755);mount("devpts", "/dev/pts", "devpts", 0, NULL);#define MAKE_STR(x) __STRING(x)mount("proc", "/proc", "proc", 0, "hidepid=2,gid=" MAKE_STR(AID_READPROC));// Don't expose the raw commandline to unprivileged processes.chmod("/proc/cmdline", 0440);gid_t groups[] = { AID_READPROC };setgroups(arraysize(groups), groups);mount("sysfs", "/sys", "sysfs", 0, NULL);mount("selinuxfs", "/sys/fs/selinux", "selinuxfs", 0, NULL);mknod("/dev/kmsg", S_IFCHR | 0600, makedev(1, 11));mknod("/dev/random", S_IFCHR | 0666, makedev(1, 8));mknod("/dev/urandom", S_IFCHR | 0666, makedev(1, 9));// Now that tmpfs is mounted on /dev and we have /dev/kmsg, we can actually// talk to the outside world...InitKernelLogging(argv); //1.3初始化系统日志系统LOG(INFO) << "init first stage started!";if (!DoFirstStageMount()) {LOG(ERROR) << "Failed to mount required partitions early ...";panic();}SetInitAvbVersionInRecovery(); //刷机模式avb版本// Set up SELinux, loading the SELinux policy.selinux_initialize(true); //1.4设置Selinux安全策略// We're in the kernel domain, so re-exec init to transition to the init domain now// that the SELinux policy has been loaded.if (selinux_android_restorecon("/init", 0) == -1) {PLOG(ERROR) << "restorecon failed";security_failure();}setenv("INIT_SECOND_STAGE", "true", 1); //设置环境变量static constexpr uint32_t kNanosecondsPerMillisecond = 1e6;uint64_t start_ms = start_time.time_since_epoch().count() / kNanosecondsPerMillisecond;setenv("INIT_STARTED_AT", std::to_string(start_ms).c_str(), 1);char* path = argv[0];char* args[] = { path, nullptr };execv(path, args); //重新执行main,进行二次初始化// execv() only returns if an error happened, in which case we// panic and never fall through this conditional.PLOG(ERROR) << "execv(\"" << path << "\") failed";security_failure();}
}

1.1 ueventd_main

通过linux提供的epoll机制监听系统的启动

int ueventd_main(int argc, char** argv) {/** init sets the umask to 077 for forked processes. We need to* create files with exact permissions, without modification by* the umask.*/umask(000);InitKernelLogging(argv);LOG(INFO) << "ueventd started!";//设置selinux会调selinux_callback cb; cb.func_log = selinux_klog_callback;selinux_set_callback(SELINUX_CB_LOG, cb);//设置冷启动 uevent 句柄DeviceHandler device_handler = CreateDeviceHandler();UeventListener uevent_listener;if (access(COLDBOOT_DONE, F_OK) != 0) {ColdBoot cold_boot(uevent_listener, device_handler);cold_boot.Run();}//epoll 冷启动 循环等待// We use waitpid() in ColdBoot, so we can't ignore SIGCHLD until now.signal(SIGCHLD, SIG_IGN);// Reap and pending children that exited between the last call to waitpid() and setting SIG_IGN// for SIGCHLD above.while (waitpid(-1, nullptr, WNOHANG) > 0) {}uevent_listener.Poll([&device_handler](const Uevent& uevent) {HandleFirmwareEvent(uevent);device_handler.HandleDeviceEvent(uevent);return ListenerAction::kContinue;});return 0;
}

1.2 watchdogd_main

通过定时喂狗的方式看门

int watchdogd_main(int argc, char **argv) {InitKernelLogging(argv);int interval = 10;if (argc >= 2) interval = atoi(argv[1]);int margin = 10;if (argc >= 3) margin = atoi(argv[2]);LOG(INFO) << "watchdogd started (interval " << interval << ", margin " << margin << ")!";int fd = open(DEV_NAME, O_RDWR|O_CLOEXEC);if (fd == -1) {PLOG(ERROR) << "Failed to open " << DEV_NAME;return 1;}//超时检测int timeout = interval + margin;int ret = ioctl(fd, WDIOC_SETTIMEOUT, &timeout); // ioctl linux内核函数if (ret) {PLOG(ERROR) << "Failed to set timeout to " << timeout;ret = ioctl(fd, WDIOC_GETTIMEOUT, &timeout);if (ret) {PLOG(ERROR) << "Failed to get timeout";} else {if (timeout > margin) {interval = timeout - margin; //计算超时时间差值} else {interval = 1;}LOG(WARNING) << "Adjusted interval to timeout returned by driver: "<< "timeout " << timeout<< ", interval " << interval<< ", margin " << margin;}}while (true) {  //循环喂狗write(fd, "", 1);sleep(interval);}
}

1.3 InitKernelLogging

void InitKernelLogging(char* argv[]) {// Make stdin/stdout/stderr all point to /dev/null.int fd = open("/sys/fs/selinux/null", O_RDWR);if (fd == -1) {int saved_errno = errno;android::base::InitLogging(argv, &android::base::KernelLogger); //写入日志errno = saved_errno;PLOG(FATAL) << "Couldn't open /sys/fs/selinux/null";}dup2(fd, 0);dup2(fd, 1);dup2(fd, 2);if (fd > 2) close(fd);android::base::InitLogging(argv, &android::base::KernelLogger);
}

##1.4 selinux_initialize

Android使用Selinux安全策略来保护系统安全,即使设备被root以后仍然能保护系统安全,除了selinux外,还有mac等保护机制。

static void selinux_initialize(bool in_kernel_domain) {Timer t;//selinux 安全上下文回调selinux_callback cb;cb.func_log = selinux_klog_callback;selinux_set_callback(SELINUX_CB_LOG, cb);cb.func_audit = audit_callback;selinux_set_callback(SELINUX_CB_AUDIT, cb);if (in_kernel_domain) {LOG(INFO) << "Loading SELinux policy";if (!selinux_load_policy()) {  //载入 selinux 安全策略panic();}bool kernel_enforcing = (security_getenforce() == 1);bool is_enforcing = selinux_is_enforcing();if (kernel_enforcing != is_enforcing) {if (security_setenforce(is_enforcing)) {PLOG(ERROR) << "security_setenforce(%s) failed" << (is_enforcing ? "true" : "false");security_failure();}}std::string err;if (!WriteFile("/sys/fs/selinux/checkreqprot", "0", &err)) {LOG(ERROR) << err;security_failure();}// init's first stage can't set properties, so pass the time to the second stage.setenv("INIT_SELINUX_TOOK", std::to_string(t.duration().count()).c_str(), 1);} else {selinux_init_all_handles(); // 处理回调}
}

2.系统孵化准备第二阶段

 // At this point we're in the second stage of init.InitKernelLogging(argv); //第二阶段日志系统初始化LOG(INFO) << "init second stage started!";// Set up a session keyring that all processes will have access to. It// will hold things like FBE encryption keys. No process should override// its session keyring.keyctl_get_keyring_ID(KEY_SPEC_SESSION_KEYRING, 1); //初始化进程会话密钥// Indicate that booting is in progress to background fw loaders, etc.close(open("/dev/.booting", O_WRONLY | O_CREAT | O_CLOEXEC, 0000)); //创建启动文件//文件属性读取配置property_init(); 2.1初始化属性系统// If arguments are passed both on the command line and in DT,// properties set in DT always have priority over the command-line ones.process_kernel_dt(); //2.2处理DT属性process_kernel_cmdline(); //处理命令行属性// Propagate the kernel variables to internal variables// used by init as well as the current required properties.export_kernel_boot_props(); //处理其他的一些属性// Make the time that init started available for bootstat to log.property_set("ro.boottime.init", getenv("INIT_STARTED_AT"));property_set("ro.boottime.init.selinux", getenv("INIT_SELINUX_TOOK"));// Set libavb version for Framework-only OTA match in Treble build.const char* avb_version = getenv("INIT_AVB_VERSION");if (avb_version) property_set("ro.boot.avb_version", avb_version);// Clean up our environment.//清空这些之前都已经存入到系统属性中去的环境变量unsetenv("INIT_SECOND_STAGE");unsetenv("INIT_STARTED_AT");unsetenv("INIT_SELINUX_TOOK");unsetenv("INIT_AVB_VERSION");// Now set up SELinux for second stage.selinux_initialize(false); //初始化SELINUXselinux_restore_context(); //重置 selinux上下文epoll_fd = epoll_create1(EPOLL_CLOEXEC); //创建Epoll文件句柄if (epoll_fd == -1) {PLOG(ERROR) << "epoll_create1 failed";exit(1);}signal_handler_init(); //2.3系统重启信号句柄初始化property_load_boot_defaults(); //加载默认启动属性export_oem_lock_status(); // ODM,即Original design manufacture(原始设计商)的缩写start_property_service(); //启动系统属性服务set_usb_controller(); //设置 usb 控制器

##2.1 property_init

void property_init() {if (__system_property_area_init()) { //系统属性初始化LOG(ERROR) << "Failed to initialize property area";exit(1);}
}

2.2 process_kernel_dt

Linux内核在启动的时候会加载dts(读取内核设备树结构)文件,此处将dt写入到系统属性中

static void process_kernel_dt() {if (!is_android_dt_value_expected("compatible", "android,firmware")) {return;}std::unique_ptr<DIR, int (*)(DIR*)> dir(opendir(get_android_dt_dir().c_str()), closedir);if (!dir) return;std::string dt_file;struct dirent *dp;while ((dp = readdir(dir.get())) != NULL) { //读取内核设备树结构if (dp->d_type != DT_REG || !strcmp(dp->d_name, "compatible") || !strcmp(dp->d_name, "name")) {continue;}std::string file_name = get_android_dt_dir() + dp->d_name;android::base::ReadFileToString(file_name, &dt_file);std::replace(dt_file.begin(), dt_file.end(), ',', '.');property_set("ro.boot."s + dp->d_name, dt_file); //写入属性}
}

2.3 signal_handler_init

通过创建socket对和设置触发动作,以及epoll监听来处理系统重启

void signal_handler_init() {// Create a signalling mechanism for SIGCHLD.//创建套接对int s[2];if (socketpair(AF_UNIX, SOCK_STREAM | SOCK_NONBLOCK | SOCK_CLOEXEC, 0, s) == -1) {PLOG(ERROR) << "socketpair failed";exit(1);}signal_write_fd = s[0];signal_read_fd = s[1];// Write to signal_write_fd if we catch SIGCHLD.struct sigaction act;memset(&act, 0, sizeof(act));act.sa_handler = SIGCHLD_handler;act.sa_flags = SA_NOCLDSTOP;sigaction(SIGCHLD, &act, 0); //设置触发actionServiceManager::GetInstance().ReapAnyOutstandingChildren(); //系统重启处理register_epoll_handler(signal_read_fd, handle_signal); //注册处理函数
}

3.系统孵化准备第三阶段

系统孵化前第三个阶段是对init.rc文件的解析,其中包括对.rc文件中 service, on, import 的解析触发以及执行,最主要的是对zygote.rc文件的解析,此外还包括一些服务的启动比如 MediaService 。

//init.rc文件解析const BuiltinFunctionMap function_map; //内建函数跳转表Action::set_function_map(&function_map); //设置表到ActionActionManager& am = ActionManager::GetInstance(); //Action解析管理ServiceManager& sm = ServiceManager::GetInstance(); //Service解析管理Parser& parser = Parser::GetInstance(); //rc文件解析parser.AddSectionParser("service", std::make_unique<ServiceParser>(&sm));parser.AddSectionParser("on", std::make_unique<ActionParser>(&am));parser.AddSectionParser("import", std::make_unique<ImportParser>(&parser));std::string bootscript = GetProperty("ro.boot.init_rc", "");if (bootscript.empty()) { //是否已存在解析脚本parser.ParseConfig("/init.rc");parser.set_is_system_etc_init_loaded(parser.ParseConfig("/system/etc/init"));parser.set_is_vendor_etc_init_loaded(parser.ParseConfig("/vendor/etc/init"));parser.set_is_odm_etc_init_loaded(parser.ParseConfig("/odm/etc/init"));} else {parser.ParseConfig(bootscript);parser.set_is_system_etc_init_loaded(true);parser.set_is_vendor_etc_init_loaded(true);parser.set_is_odm_etc_init_loaded(true);}// Turning this on and letting the INFO logging be discarded adds 0.2s to// Nexus 9 boot time, so it's disabled by default.if (false) DumpState();//触发系列动作am.QueueEventTrigger("early-init"); // Queue an action that waits for coldboot done so we know ueventd has set up all of /dev...am.QueueBuiltinAction(wait_for_coldboot_done_action, "wait_for_coldboot_done");// ... so that we can start queuing up actions that require stuff from /dev.am.QueueBuiltinAction(mix_hwrng_into_linux_rng_action, "mix_hwrng_into_linux_rng");am.QueueBuiltinAction(set_mmap_rnd_bits_action, "set_mmap_rnd_bits");am.QueueBuiltinAction(set_kptr_restrict_action, "set_kptr_restrict");am.QueueBuiltinAction(keychord_init_action, "keychord_init");am.QueueBuiltinAction(console_init_action, "console_init");// Trigger all the boot actions to get us started.am.QueueEventTrigger("init");// Repeat mix_hwrng_into_linux_rng in case /dev/hw_random or /dev/random// wasn't ready immediately after wait_for_coldboot_doneam.QueueBuiltinAction(mix_hwrng_into_linux_rng_action, "mix_hwrng_into_linux_rng");// charger 模式不挂在文件系统std::string bootmode = GetProperty("ro.bootmode", "");if (bootmode == "charger") {am.QueueEventTrigger("charger");} else {am.QueueEventTrigger("late-init");}// Run all property triggers based on current state of the properties.am.QueueBuiltinAction(queue_property_triggers_action, "queue_property_triggers");while (true) { //进入循环等待// By default, sleep until something happens.int epoll_timeout_ms = -1;if (do_shutdown && !shutting_down) { //关机状态do_shutdown = false;if (HandlePowerctlMessage(shutdown_command)) {shutting_down = true;}}if (!(waiting_for_prop || sm.IsWaitingForExec())) {am.ExecuteOneCommand(); //执行command}//是否执行进程重启if (!(waiting_for_prop || sm.IsWaitingForExec())) {if (!shutting_down) restart_processes();// If there's a process that needs restarting, wake up in time for that.if (process_needs_restart_at != 0) {epoll_timeout_ms = (process_needs_restart_at - time(nullptr)) * 1000;if (epoll_timeout_ms < 0) epoll_timeout_ms = 0;}// If there's more work to do, wake up again immediately.if (am.HasMoreCommands()) epoll_timeout_ms = 0;}// epoll 事件处理epoll_event ev;int nr = TEMP_FAILURE_RETRY(epoll_wait(epoll_fd, &ev, 1, epoll_timeout_ms));if (nr == -1) {PLOG(ERROR) << "epoll_wait failed";} else if (nr == 1) {((void (*)()) ev.data.ptr)();}}return 0;

3.1 BuiltinFunctionMap

内建函数表用于解析后 InvockFunc 函数回调

const BuiltinFunctionMap::Map& BuiltinFunctionMap::map() const { //内建函数跳转表constexpr std::size_t kMax = std::numeric_limits<std::size_t>::max();// clang-format offstatic const Map builtin_functions = {{"bootchart",               {1,     1,    do_bootchart}},{"chmod",                   {2,     2,    do_chmod}},{"chown",                   {2,     3,    do_chown}},{"class_reset",             {1,     1,    do_class_reset}},{"class_restart",           {1,     1,    do_class_restart}},{"class_start",             {1,     1,    do_class_start}},{"class_stop",              {1,     1,    do_class_stop}},{"copy",                    {2,     2,    do_copy}},{"domainname",              {1,     1,    do_domainname}},{"enable",                  {1,     1,    do_enable}},{"exec",                    {1,     kMax, do_exec}},{"exec_start",              {1,     1,    do_exec_start}},{"export",                  {2,     2,    do_export}},{"hostname",                {1,     1,    do_hostname}},{"ifup",                    {1,     1,    do_ifup}},{"init_user0",              {0,     0,    do_init_user0}},{"insmod",                  {1,     kMax, do_insmod}},{"installkey",              {1,     1,    do_installkey}},{"load_persist_props",      {0,     0,    do_load_persist_props}},{"load_system_props",       {0,     0,    do_load_system_props}},{"loglevel",                {1,     1,    do_loglevel}},{"mkdir",                   {1,     4,    do_mkdir}},{"mount_all",               {1,     kMax, do_mount_all}},{"mount",                   {3,     kMax, do_mount}},{"umount",                  {1,     1,    do_umount}},{"restart",                 {1,     1,    do_restart}},{"restorecon",              {1,     kMax, do_restorecon}},{"restorecon_recursive",    {1,     kMax, do_restorecon_recursive}},{"rm",                      {1,     1,    do_rm}},{"rmdir",                   {1,     1,    do_rmdir}},{"setprop",                 {2,     2,    do_setprop}},{"setrlimit",               {3,     3,    do_setrlimit}},{"start",                   {1,     1,    do_start}},{"stop",                    {1,     1,    do_stop}},{"swapon_all",              {1,     1,    do_swapon_all}},{"symlink",                 {2,     2,    do_symlink}},{"sysclktz",                {1,     1,    do_sysclktz}},{"trigger",                 {1,     1,    do_trigger}},{"verity_load_state",       {0,     0,    do_verity_load_state}},{"verity_update_state",     {0,     0,    do_verity_update_state}},{"wait",                    {1,     2,    do_wait}},{"wait_for_prop",           {2,     2,    do_wait_for_prop}},{"write",                   {2,     2,    do_write}},};// clang-format onreturn builtin_functions;
}

3.2 AddSectionParser

section_parsers_数组包含 service , on , import 分别对应 servie解析,action解析,import解析

Parser& Parser::GetInstance() {static Parser instance;return instance;
}void Parser::AddSectionParser(const std::string& name,std::unique_ptr<SectionParser> parser) {section_parsers_[name] = std::move(parser); //service,on,import 加入解析数组
}void Parser::AddSingleLineParser(const std::string& prefix, LineCallback callback) {line_callbacks_.emplace_back(prefix, callback);
}

3.3 ParseConfig

bool Parser::ParseConfig(const std::string& path) {if (is_dir(path.c_str())) {return ParseConfigDir(path); //查找dir}return ParseConfigFile(path); //解析文件
}

解析文件

bool Parser::ParseConfigFile(const std::string& path) {LOG(INFO) << "Parsing file " << path << "...";android::base::Timer t;std::string data;std::string err;if (!ReadFile(path, &data, &err)) {LOG(ERROR) << err;return false;}data.push_back('\n'); // TODO: fix parse_config.ParseData(path, data); //解析文件数据for (const auto& [section_name, section_parser] : section_parsers_) {section_parser->EndFile();}LOG(VERBOSE) << "(Parsing " << path << " took " << t << ".)";return true;
}

调用具体解析

void Parser::ParseData(const std::string& filename, const std::string& data) {//TODO: Use a parser with const input and remove this copystd::vector<char> data_copy(data.begin(), data.end());data_copy.push_back('\0');parse_state state; //解析状态结构state.line = 0;state.ptr = &data_copy[0];state.nexttoken = 0;SectionParser* section_parser = nullptr;std::vector<std::string> args;for (;;) {switch (next_token(&state)) {case T_EOF:if (section_parser) {section_parser->EndSection();}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.for (const auto& [prefix, callback] : line_callbacks_) {if (android::base::StartsWith(args[0], prefix.c_str())) {if (section_parser) section_parser->EndSection(); // 结束std::string ret_err;if (!callback(std::move(args), &ret_err)) {LOG(ERROR) << filename << ": " << state.line << ": " << ret_err;}section_parser = nullptr;break;}}if (section_parsers_.count(args[0])) { if (section_parser) {section_parser->EndSection();}section_parser = section_parsers_[args[0]].get();std::string ret_err;//执行段解析if (!section_parser->ParseSection(std::move(args), filename, state.line, &ret_err)) {LOG(ERROR) << filename << ": " << state.line << ": " << ret_err;section_parser = nullptr;}} else if (section_parser) {std::string ret_err;//执行行解析if (!section_parser->ParseLineSection(std::move(args), state.line, &ret_err)) {LOG(ERROR) << filename << ": " << state.line << ": " << ret_err;}}args.clear();break;case T_TEXT:args.emplace_back(state.text);break;}}
}

按字符解析.rc文件


int next_token(struct parse_state *state)
{char *x = state->ptr;char *s;if (state->nexttoken) {int t = state->nexttoken; //取下一tokenstate->nexttoken = 0;return t;}for (;;) {switch (*x) {case 0:state->ptr = x;return T_EOF; //文件结束case '\n':x++;state->ptr = x;return T_NEWLINE; //下一行case ' ':case '\t':case '\r':x++;continue; //空格继续case '#':while (*x && (*x != '\n')) x++;if (*x == '\n') {state->ptr = x+1;return T_NEWLINE;} else {state->ptr = x;return T_EOF;}default:goto text;}}textdone:state->ptr = x;*s = 0;return T_TEXT;
text:state->text = s = x;
textresume:for (;;) {switch (*x) {case 0:goto textdone;case ' ':case '\t':case '\r':x++;goto textdone;case '\n':state->nexttoken = T_NEWLINE;x++;goto textdone;case '"':x++;for (;;) {switch (*x) {case 0:/* unterminated quoted thing */state->ptr = x;return T_EOF;case '"':x++;goto textresume;default:*s++ = *x++;}}break;case '\\': //注释x++;switch (*x) {case 0:goto textdone;case 'n':*s++ = '\n';break;case 'r':*s++ = '\r';break;case 't':*s++ = '\t';break;case '\\':*s++ = '\\';break;case '\r':/* \ <cr> <lf> -> line continuation */if (x[1] != '\n') {x++;continue;}case '\n':/* \ <lf> -> line continuation */state->line++;x++;/* eat any extra whitespace */while((*x == ' ') || (*x == '\t')) x++;continue;default:/* unknown escape -- just copy */*s++ = *x++;}continue;default:*s++ = *x++;}}return T_EOF;
}

解析Action

bool ActionParser::ParseSection(std::vector<std::string>&& args, const std::string& filename,int line, std::string* err) {std::vector<std::string> triggers(args.begin() + 1, args.end());if (triggers.size() < 1) {*err = "actions must have a trigger";return false;}auto action = std::make_unique<Action>(false, filename, line);if (!action->InitTriggers(triggers, err)) { //触发解析return false;}action_ = std::move(action);return true;
}

3.3 ExecuteOneCommand

执行解析命令

void Action::ExecuteOneCommand(std::size_t command) const {// We need a copy here since some Command execution may result in// changing commands_ vector by importing .rc files through parserCommand cmd = commands_[command];ExecuteCommand(cmd);
}

InvokeFunc()函数回调

void Action::ExecuteCommand(const Command& command) const {android::base::Timer t;int result = command.InvokeFunc(); //执行函数表跳转auto duration = t.duration();// Any action longer than 50ms will be warned to user as slow operationif (duration > 50ms || android::base::GetMinimumLogSeverity() <= android::base::DEBUG) {std::string trigger_name = BuildTriggersString();std::string cmd_str = command.BuildCommandString();LOG(INFO) << "Command '" << cmd_str << "' action=" << trigger_name << " (" << filename_<< ":" << command.line() << ") returned " << result << " took "<< duration.count() << "ms.";}
}

执行类启动

static int do_class_start(const std::vector<std::string>& args) {/* Starting a class does not start services* which are explicitly disabled.  They must* be started individually.*/ServiceManager::GetInstance().ForEachServiceInClass(args[1], [] (Service* s) { s->StartIfNotDisabled(); });return 0;
}

函数do_class_start函数在表中的位置

static const Map builtin_functions = {{"bootchart",               {1,     1,    do_bootchart}},{"chmod",                   {2,     2,    do_chmod}},{"chown",                   {2,     3,    do_chown}},{"class_reset",             {1,     1,    do_class_reset}},{"class_restart",           {1,     1,    do_class_restart}},{"class_start",             {1,     1,    do_class_start}},......

3.4 .rc文件

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
import /init.${ro.zygote}.rc

zygote.rc文件

service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-serverclass mainpriority -20user rootgroup root readprocsocket zygote stream 660 root systemonrestart write /sys/android_power/request_state wakeonrestart write /sys/power/state ononrestart restart audioserveronrestart restart cameraserveronrestart restart mediaonrestart restart netdonrestart restart wificondwritepid /dev/cpuset/foreground/tasks

4 .进入系统孵化阶段

int main(int argc, char* const argv[])
{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)); //初始化运行时// Process command line arguments// ignore argv[0]//忽略argv[0]argc--;argv++;//解析规则// --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. 进程优先级const char* spaced_commands[] = { "-cp", "-classpath" };// Allow "spaced commands" to be succeeded by exactly 1 argument (regardless of -s).bool known_command = false;......
}

至此,系统孵化准备工作完毕,接下来是系统将进入孵化阶段,孵化阶段将会启动Zygote, AndroidRuntime, SystemServer, JVM环境初始化等等,孵化阶段将提供JAVA运行环境,为后续启动系统服务提供基本保障,孵化阶段还为应用的创建提供高效的措施。

Android8.0 系统启动之孵化准备相关推荐

  1. Android 8.0系统启动流程_Launcher(四)

    本系列主要介绍Android8.0系统启动过程中涉及到的init.Zygote.SystemServer和Launcher. 在之前的三篇文章中,讲解了如下的过程: 初始化化:电源上电,加载BootL ...

  2. Android10.0系统启动之Launcher(桌面)启动流程-[Android取经之路]

    摘要:上一节我们讲完了Android10.0的ActivityManagerService的启动流程,在AMS的最后启动了Launcher进程,今天我们就来看看Launcher的真正启动流程. 阅读本 ...

  3. Android 10.0 系统启动之SystemServer进程-[Android取经之路]

    摘要:上一节讲解了Zygote进程的整个启动流程.Zygote是所有应用的鼻祖.SystemServer和其他所有Dalivik虚拟机进程都是由Zygote fork而来.Zygote fork的第一 ...

  4. android 打印kernel log,android8.0 kernel4.9.44 各层log打开

    一.问题 平台android8.0 kernel4.9.44,想加个i2c驱动,打开log都是一件脑瓜疼的事. 二.log总结 android有三种log. 1.kernel下面的,就是driver层 ...

  5. Android10.0系统启动之Zygote进程-[Android取经之路]

    [Android取经之路] 的源码都基于Android-Q(10.0) 进行分析 [Android取经之路] 系列文章: <系统启动篇> Android系统架构 Android是怎么启动的 ...

  6. Android深入四大组件(六)Android8.0 根Activity启动过程(前篇)

    相关文章 Android深入四大组件系列 Android系统启动系列 Android应用程序进程系列 Android深入解析AMS系列 前言 在几个月前我写了Android深入四大组件(一)应用程序启 ...

  7. Android深入四大组件(七)Android8.0 根Activity启动过程(后篇)

    相关文章 Android深入四大组件系列 Android系统启动系列 Android应用程序进程系列 Android深入解析AMS系列 前言 在几个月前我写了Android深入四大组件(一)应用程序启 ...

  8. android8显示广播,关于android8.0静态接收广播

    android8.0很多广播不能静态注册接受 查看log显示 Background execution not allowed: receiving 查看代码frameworks/base/servi ...

  9. Android8.0运行时权限策略变化和适配方案

    版权声明:转载必须注明本文转自严振杰的博客:http://blog.yanzhenjie.com Android8.0也就是Android O即将要发布了,有很多新特性,目前我们可以通过Android ...

最新文章

  1. 一套外企的数据库设计面试题
  2. python数据库查询怎么用变量_python中带变量的SQL查询
  3. requestmapping配置页面后_@RequestMapping接口及页面乱码问题
  4. 网易云信与林鹿科技联手推出云对讲服务
  5. TCP/IP的二层负载
  6. 聊城大学计算机学院答辩,数学与信息工程系成功举办精品课程答辩会
  7. reuse project css less path folder hierarchy issue
  8. 对称加密算法原理与常用实现
  9. filezilla 共享多个目录_filezilla设置中文,3步搞定filezilla中文设置
  10. python计算近似圆周率
  11. mysql搜索结果去重_MySQL去除查询结果重复
  12. 这款工具不用手写一行代码就能做出网站!
  13. 超级列表框排序mysql_超级列表框排序
  14. 百度硬盘和Google桌面的比较
  15. 控制系统中对信号求导的注意事项
  16. IP签名档美化版api源码PHP
  17. MySQL查看锁及事务隔离级别的命令
  18. api zoom 实现自动预定_一种基于Web端API的网络地图图片自动截取拼接的方法与流程...
  19. 【APICloud系列|31】成功上架5个应用商店总结(腾讯应用宝、阿里应用分发平台、华为开发者联盟、小米开放平台、百度开放平台)
  20. Hibernate之HQL

热门文章

  1. “%,/,//”的用法
  2. 广汉哪里可以学计算机,广汉的年轻人学门啥技术好找工作呢
  3. k/3 Cloud如何从菜鸟成长一名合格的ERP开发工程师
  4. 音视频编解码基础知识(1)- 音视频编解码过程
  5. 《信息物理融合系统(CPS)设计、建模与仿真——基于 Ptolemy II 平台》——1.6 异构建模的方法...
  6. Java 在PDF中添加骑缝章
  7. 微信小游戏直播在Android端的跨进程渲染推流实践
  8. 关于Office 365 显示语言的设置(注册开通时的语言选择及注册开通后的语言显示修改)
  9. 案件被终本后,如何继续执行?
  10. 自己动手写H3C校园网登录客户端(Linux平台版)