Android R开机流程跟踪-----init.rc和启动Zygote
概述
init.rc是非常重要的配置文件,它是由Android 初始化语言(Android Init Language)编写的脚本,这种语言主要包含5种类型语句:Action、Command、Service、Option和Import。
具体语法可以查阅README.md,位于:Android11\system\core\init,在这里语法不具体发散,详情网上查阅,有很多资料。
nit.rc有两个,分别位于:
Android11/system/core/rootdir/init.rc
Android11/bootable/recovery/etc/init.rc
在Android11/system/core/rootdir/init.rc中,关注一句:import /system/etc/init/hw/init.${ro.zygote}.rc
一个是设备文件路径(机器里面的路径),一个是代码文件路径,不要搞混了。
查询机器的系统属性getprop ro.zygote 得:zygote32,所以RT51R是32位系统。
在机器路径/system/etc/init/hw,ls得:init.rc处的import /system/etc/init/hw/init.${ro.zygote}.rc,就是init.zygote32.rc。
init启动Zygote
`class_start <serviceclass>`
> Start all services of the specified class if they are
not already running. See the start entry for more information on
starting services.
command是action的命令列表中的命令,或者是service中的选项 onrestart 的参数命令,命令将在所属事件发生时被一个个地执行.
列举常用的命令
class_start <service_class_name>: 启动属于同一个class的所有服务;
class_stop <service_class_name> : 停止指定类的服务
start <service_name>: 启动指定的服务,若已启动则跳过;
stop <service_name>: 停止正在运行的服务
setprop <name> <value>:设置属性值
mkdir <path>:创建指定目录
symlink <target> <sym_link>: 创建连接到<target>的<sym_link>符号链接;
write <path> <string>: 向文件path中写入字符串;
exec: fork并执行,会阻塞init进程直到程序完毕;
exprot <name> <name>:设定环境变量;
loglevel <level>:设置log级别
hostname <name> : 设置主机名
import <filename> :导入一个额外的init配置文件
init.rc解析:
介绍从SecondStageMain到do_class_start这一执行流程如下:
在init.rc中有如下配置代码:
on nonencrypted
class_start main
class_start late_start
其中class_star是一个COMMAND,对应的函数为do_class_start。启动init.rc中那些设ClassName为main的Service。Zygote的classname就是main,因此class_start main是用来启动Zygote的。do_class_start函数在builtins.cpp中定义。do_class_start在上述流程图中,最后被InvokeFunc调用。
init启动Zygote32.rc
文件内容如下:
service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server //进程名为Zygote,执行程序为app_process
class main //classname为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 exec_background - system system -- /system/bin/vdc volume abort_fuse
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
Services
Services are programs which init launches and (optionally) restarts
when they exit. Services take the form of:
service <name> <pathname> [ <argument> ]* //<service 的名字><执行程序路径><传递参数>
<option> //option是Service的修饰词,影响什么时候、如何启动Service
<option>
...
Zygote启动流程
1、builtins.cpp的函数:do_class_start
2、service.cpp的函数:StartIfNotDisabled
如果Service没有在其对应的rc文件中设置disable选项,则会调用Start()函数启动该Service,Zygote32.rc中没有设置disable选项,因此会执行Start函数。
3、Start函数:
Result<void> Service::Start() {
……
if (flags_ & SVC_RUNNING) { //如果 Service已经运行,则不启动
if ((flags_ & SVC_ONESHOT) && disabled) {
flags_ |= SVC_RESTART;
}
// It is not an error to try to start a service that is already running.
reboot_on_failure.Disable();
return {};
}
bool needs_console = (flags_ & SVC_CONSOLE);
if (needs_console) {
if (proc_attr_.console.empty()) {
proc_attr_.console = "/dev/" + GetProperty("ro.boot.console", "console");
}
// Make sure that open call succeeds to ensure a console driver is
// properly registered for the device node
int console_fd = open(proc_attr_.console.c_str(), O_RDWR | O_CLOEXEC);
if (console_fd < 0) {
flags_ |= SVC_DISABLED;
return ErrnoError() << "Couldn't open console '" << proc_attr_.console << "'";
}
close(console_fd);
}
//判断需要启动的Service的对应的执行文件是否存在,不存在则不启动该Service
struct stat sb;
if (stat(args_[0].c_str(), &sb) == -1) {
flags_ |= SVC_DISABLED;
return ErrnoError() << "Cannot find '" << args_[0] << "'";
}
……
pid_t pid = -1;
if (namespaces_.flags) {
pid = clone(nullptr, nullptr, namespaces_.flags | SIGCHLD, nullptr);
} else {
pid = fork(); //如果子进程没有启动,则调用fork函数创建子进程
}
if (pid == 0) { //当前代码逻辑在子进程中运行
umask(077);
if (auto result = EnterNamespaces(namespaces_, name_, pre_apexd_); !result.ok()) {
LOG(FATAL) << "Service '" << name_
<< "' failed to set up namespaces: " << result.error();
}
for (const auto& [key, value] : environment_vars_) {
setenv(key.c_str(), value.c_str(), 1);
}
for (const auto& descriptor : descriptors) {
descriptor.Publish();
}
if (auto result = WritePidToFiles(&writepid_files_); !result.ok()) {
LOG(ERROR) << "failed to write pid to files: " << result.error();
}
if (task_profiles_.size() > 0 && !SetTaskProfiles(getpid(), task_profiles_)) {
LOG(ERROR) << "failed to set task profiles";
}
// As requested, set our gid, supplemental gids, uid, context, and
// priority. Aborts on failure.
SetProcessAttributesAndCaps();
if (!ExpandArgsAndExecv(args_, sigstop_)) { //调用execve函数,子进程就会被启动
PLOG(ERROR) << "cannot execv('" << args_[0]
<< "'). See the 'Debugging init' section of init's README.md for tips";
}
_exit(127);
}
……
return {};
}
4、ExpandArgsAndExecv函数:
//调用execve函数,子进程就会被启动
static bool ExpandArgsAndExecv(const std::vector<std::string>& args, bool sigstop) {
std::vector<std::string> expanded_args;
std::vector<char*> c_strings;
expanded_args.resize(args.size());
c_strings.push_back(const_cast<char*>(args[0].data()));
for (std::size_t i = 1; i < args.size(); ++i) {
auto expanded_arg = ExpandProps(args[i]);
if (!expanded_arg.ok()) {
LOG(FATAL) << args[0] << ": cannot expand arguments': " << expanded_arg.error();
}
expanded_args[i] = *expanded_arg;
c_strings.push_back(expanded_args[i].data());
}
c_strings.push_back(nullptr);
if (sigstop) {
kill(getpid(), SIGSTOP);
}
return execv(c_strings[0], c_strings.data()) == 0;
}
5、app_main.cpp的main函数:
Service子进程被启动,并进去该service的main函数中,Zygote执行程序的路径为/system/bin/app_process,对应的文件为app_main.cpp,这样就会进去app_main.cpp的main函数中,也就是Zygote的main函数。
int main(int argc, char* const argv[])
{
……
if (zygote) {
runtime.start("com.android.internal.os.ZygoteInit", args, zygote);
} else if (className) {
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.");
}
}
调用runtime的start函数启动Zygote,至此Zygote就启动了。