struct cmdinfo cmds[] = {
{ "ping", 0, do_ping },
{ "create_app_data", 7, do_create_app_data },
{ "restorecon_app_data", 6, do_restorecon_app_data },
{ "migrate_app_data", 4, do_migrate_app_data },
{ "clear_app_data", 5, do_clear_app_data },
{ "destroy_app_data", 5, do_destroy_app_data },
{ "move_complete_app", 7, do_move_complete_app },
{ "get_app_size", 6, do_get_app_size },
{ "get_app_data_inode", 4, do_get_app_data_inode },
{ "create_user_data", 4, do_create_user_data },
{ "destroy_user_data", 3, do_destroy_user_data },
//odex 优化
{ "dexopt", 10, do_dexopt },
{ "markbootcomplete", 1, do_mark_boot_complete },
{ "rmdex", 2, do_rm_dex },
{ "freecache", 2, do_free_cache },
{ "linklib", 4, do_linklib },
{ "idmap", 3, do_idmap },
{ "createoatdir", 2, do_create_oat_dir },
{ "rmpackagedir", 1, do_rm_package_dir },
{ "clear_app_profiles", 1, do_clear_app_profiles },
{ "destroy_app_profiles", 1, do_destroy_app_profiles },
{ "linkfile", 3, do_link_file },
{ "move_ab", 3, do_move_ab },
{ "merge_profiles", 2, do_merge_profiles },
{ "dump_profiles", 3, do_dump_profiles },
{ "delete_odex", 3, do_delete_odex },
};
const BuiltinFunctionMap function\_map;
Action::set\_function\_map(&function\_map);
Parser& parser = Parser::GetInstance();
parser.AddSectionParser("service",std::make\_unique<ServiceParser>());
parser.AddSectionParser("on", std::make\_unique<ActionParser>());
parser.AddSectionParser("import", std::make\_unique<ImportParser>());
parser.ParseConfig("/init.rc");
ActionManager& am = ActionManager::GetInstance();
am.QueueEventTrigger("early-init");
..........................
// Trigger all the boot actions to get us started.
am.QueueEventTrigger("init");
.........................
std::string bootmode = property\_get("ro.bootmode");
if (bootmode == "charger") {
am.QueueEventTrigger("charger");
} else if (strncmp(bootmode.c\_str(), "ffbm", 4) == 0) {
NOTICE("Booting into ffbm mode\n");
am.QueueEventTrigger("ffbm");
} 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");
...............................
}
*.rc 中如何解析相关脚本,参看如下方法定义:
system/core/init/builtins.cpp
BuiltinFunctionMap::Map& BuiltinFunctionMap::map() const {
constexpr std::size\_t kMax = std::numeric\_limits<std::size\_t>::max();
static const Map builtin\_functions = {
{"bootchart\_init", {0, 0, do\_bootchart\_init}},
{"chmod", {2, 4, do\_chmod}},
{"chown", {2, 5, do\_chown}},
{"class\_reset", {1, 1, do\_class\_reset}},
{"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}},
{"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}},
{"powerctl", {1, 1, do\_powerctl}},
{"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}},
{"write", {2, 4, do\_write}},
};
return builtin\_functions;
}
static int do_mount_all(const std::vector<std::string>& args) {
std::size\_t na = 0;
bool import\_rc = true;
bool queue\_event = true;
int mount\_mode = MOUNT\_MODE\_DEFAULT;
const char\* fstabfile = args[1].c\_str();
std::size\_t path\_arg\_end = args.size();
.................
int ret = mount\_fstab(fstabfile, mount\_mode);
................
if (import\_rc) {
/\* Paths of .rc files are specified at the 2nd argument and beyond \*/
import\_late(args, 2, path\_arg\_end);
}
......................
}
static void import_late(const std::vector<std::string>& args, size_t start_index, size_t end_index) {
Parser& parser = Parser::GetInstance();
if (end\_index <= start\_index) {
// Use the default set if no path is given
static const std::vector<std::string> init\_directories = {
//执行到该目录,读取*.rc 解析
"/system/etc/init",
"/vendor/etc/init",
"/odm/etc/init"
};
for (const auto& dir : init\_directories) {
parser.ParseConfig(dir);
}
} else {
for (size\_t i = start\_index; i < end\_index; ++i) {
parser.ParseConfig(args[i]);
}
}
}
static int installd_main(const int argc ATTRIBUTE_UNUSED, char *argv[]) {
char buf[BUFFER_MAX];
struct sockaddr addr;
socklen_t alen;
int lsocket, s;
int selinux_enabled = (is_selinux_enabled() > 0);
setenv("ANDROID_LOG_TAGS", "*:v", 1);
android::base::InitLogging(argv);
ALOGI("installd firing up\n");
union selinux_callback cb;
cb.func_log = log_callback;
selinux_set_callback(SELINUX_CB_LOG, cb);
if (!initialize_globals()) {
ALOGE("Could not initialize globals; exiting.\n");
exit(1);
}
if (initialize_directories() < 0) {
ALOGE("Could not create directories; exiting.\n");
exit(1);
}
if (selinux_enabled && selinux_status_open(true) < 0) {
ALOGE("Could not open selinux status; exiting.\n");
exit(1);
}
//创建服务端socket
lsocket = android_get_control_socket(SOCKET_PATH); //#define SOCKET_PATH "installd"
if (lsocket < 0) {
ALOGE("Failed to get socket from environment: %s\n", strerror(errno));
exit(1);
}
if (listen(lsocket, 5)) {
ALOGE("Listen on socket failed: %s\n", strerror(errno));
exit(1);
}
fcntl(lsocket, F_SETFD, FD_CLOEXEC);
for (;;) {
alen = sizeof(addr);
s = accept(lsocket, &addr, &alen);
if (s < 0) {
ALOGE("Accept failed: %s\n", strerror(errno));
continue;
}
fcntl(s, F_SETFD, FD_CLOEXEC);
ALOGI("new connection\n");
for (;;) {
unsigned short count;
if (readx(s, &count, sizeof(count))) {
ALOGE("failed to read size\n");
break;
}
if ((count < 1) || (count >= BUFFER_MAX)) {
ALOGE("invalid size %d\n", count);
break;
}
if (readx(s, buf, count)) {
ALOGE("failed to read command\n");
break;
}
buf[count] = 0;
if (selinux_enabled && selinux_status_updated() > 0) {
selinux_android_seapp_context_reload();
}
if (execute(s, buf)) break;
}
ALOGI("closing connection\n");
close(s);
}
return 0;
}
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。