Android init与zygote启动
Posted cao_null
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android init与zygote启动相关的知识,希望对你有一定的参考价值。
init是android用户空间启动的第一个进程。
代码基于Android 8
涉及类路径
/system/core/init/init.cpp
/system/core/rootdir/init.rc
/system/core/init/init_parser.cpp
/system/core/init/action.cpp
/system/core/init/keyword_map.h
/system/core/init/service.cpp
/system/core/rootdir/init.zygote64_32.rc
/system/core/rootdir/目录下有多个文件
这里能看到init.rc还有zygote32和64位的单独版本,分别对应32位和64位系统。还有init.zygote32_64.rc,代表会启动两个进程,主进程是32。
init.rc
接下来具体看看init.rc都做了什么
可以通过readme先熟悉语法
//README.md
//暂时只关注最关键的部分
The intention of these directories is:
//核心
1. /system/etc/init/ is for core system items such as
SurfaceFlinger, MediaService, and logcatd.
//SoC
2. /vendor/etc/init/ is for SoC vendor items such as actions or
daemons needed for core SoC functionality.
//odm制造商
3. /odm/etc/init/ is for device manufacturer items such as
actions or daemons needed for motion sensor or other peripheral
functionality.
//然后是具体的语法
//一组trigger触发的命令
Actions
on <trigger> [&& <trigger>]*
<command>
<command>
<command>
//init启动的服务,能重启
Services
service <name> <pathname> [ <argument> ]*
<option>
<option>
//services参数
Options
`console [<console>]`
//判断条件触发器
Triggers
`on property:a=b && property:c=d` defines an action that is executed
//具体命令
Commands
`bootchart [start|stop]`
//api不贴了用到再查
//init.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
on early-init
# Set init and its forked children's oom_adj.
write /proc/1/oom_score_adj -1000
# Disable sysrq from keyboard
write /proc/sys/kernel/sysrq 0
# Set the security context of /adb_keys if present.
restorecon /adb_keys
... //各种初始化
on init
//boot时候的操作,大量文件句柄创建
...
# Mount filesystems and start core system services.
on late-init
...
//启动zygote
# Now we can start zygote for devices with file based encryption
trigger zygote-start
# Load persist properties and override properties (if enabled) from /data.
trigger load_persist_props_action
# Remove a file to wake up anything waiting for firmware.
trigger firmware_mounts_complete
trigger early-boot
trigger boot
...
# It is recommended to put unnecessary data/ initialization from post-fs-data
# to start-zygote in device's init.rc to unblock zygote start.
//不同参数启动zygote
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 zygote
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
on boot
# basic network init
ifup lo
hostname localhost
domainname localdomain
# Memory management. Basic kernel parameters, and allow the high
# level system server to be able to adjust the kernel OOM driver
# parameters to match how it is managing things.
write /proc/sys/vm/overcommit_memory 1
write /proc/sys/vm/min_free_order_shift 4
chown root system /sys/module/lowmemorykiller/parameters/adj
chmod 0664 /sys/module/lowmemorykiller/parameters/adj
chown root system /sys/module/lowmemorykiller/parameters/minfree
chmod 0664 /sys/module/lowmemorykiller/parameters/minfree
...//各种权限等操作
//启动hal
# Start standard binderized HAL daemons
class_start hal
class_start core
...
//启动各种service
service console /system/bin/sh
class core
console
disabled
user shell
group shell log readproc
seclabel u:r:shell:s0
on property:ro.debuggable=1
# Give writes to anyone for the trace folder on debug builds.
# The folder is used to store method traces.
chmod 0773 /data/misc/trace
start console
service flash_recovery /system/bin/install-recovery.sh
class main
oneshot
init入口
Parser负责上面配置文件的解析
//init.cpp
#include <android-base/file.h>
#include <android-base/properties.h>
#include "init_parser.h"
using android::base::GetProperty;
using android::base::StringPrintf;
int main(int argc, char** argv) {
...
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>());
std::string bootscript = GetProperty("ro.boot.init_rc", "");
//判断ro.boot.init_rc属性是否是空
if (bootscript.empty()) {
//依次取init.rc
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);
}
...
if (bootmode == "charger") {
am.QueueEventTrigger("charger");
} else {
am.QueueEventTrigger("late-init");//init最后会执行late-init
}
}
Parser对应着init_parser.cpp
//init_parser.cpp
void Parser::AddSectionParser(const std::string& name,
std::unique_ptr<SectionParser> parser) {
section_parsers_[name] = std::move(parser);
}
配置语句,on early-init 用到的SectionParser实际上对应着init.cpp传入的子类ActionParser 。先看/system/core/init/action.cpp里面的ParseSection方法。
//action.cpp
bool Action::ParsePropertyTrigger(const std::string& trigger, std::string* err) {
const static std::string prop_str("property:");
std::string prop_name(trigger.substr(prop_str.length()));
//=分割成键值对
size_t equal_pos = prop_name.find('=');
if (equal_pos == std::string::npos) {
*err = "property trigger found without matching '='";
return false;
}
std::string prop_value(prop_name.substr(equal_pos + 1));
prop_name.erase(equal_pos);
if (auto [it, inserted] = property_triggers_.emplace(prop_name, prop_value); !inserted) {
*err = "multiple property triggers found for same property";
return false;
}
return true;
}
重点看ParseLineSection
//system/core/init/action.cpp
bool ActionParser::ParseLineSection(const std::vector<std::string>& args,
const std::string& filename, int line,
std::string* err) const {
//调用AddCommand
return action_ ? action_->AddCommand(args, filename, line, err) : false;
}
bool Action::AddCommand(const std::vector<std::string>& args,
const std::string& filename, int line, std::string* err) {
if (!function_map_) {
*err = "no function map available";
return false;
}
if (args.empty()) {
*err = "command needed, but not provided";
return false;
}
//传入FindFunction
auto function = function_map_->FindFunction(args[0], args.size() - 1, err);
if (!function) {
return false;
}
AddCommand(function, args, filename, line);
return true;
}
FindFunction定义在/system/core/init/keyword_map.h,最终map()由/system/core/init/builtins.cpp来定义
//system/core/init/builtins.cpp
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 = {
{"bootchart", {1, 1, do_bootchart}},
{"chmod", {2, 2, do_chmod}},
{"chown", {2, 3, do_chown}},
...
{"start", {1, 1, do_start}},
...
};
// clang-format on
return builtin_functions;
}
回头来看start zygote,对应执行do_start方法
//system/core/init/builtins.cpp
static int do_start(const std::vector<std::string>& args) {
//通过名称搜索对应Service
Service* svc = ServiceManager::GetInstance().FindServiceByName(args[1]);
if (!svc) {
LOG(ERROR) << "do_start: Service " << args[1] << " not found";
return -1;
}
//执行Start方法
if (!svc->Start())
return -1;
return 0;
}
跳转到Service.cpp
//system/core/init/service.cpp
bool Service::Start() {
...
//各种检查忽略
LOG(INFO) << "starting service '" << name_ << "'...";
pid_t pid = -1;
if (namespace_flags_) {
//有namespace_flags_则clone子进程
pid = clone(nullptr, nullptr, namespace_flags_ | SIGCHLD, nullptr);
} else {
//否则fork子进程
pid = fork();
}
if (pid == 0) {
std::vector<char*> strs;
ExpandArgs(args_, &strs);//先展开参数
//然后执行
if (execve(strs[0], (char**) &strs[0], (char**) ENV) < 0) {
PLOG(ERROR) << "cannot execve('" << strs[0] << "')";
}
_exit(127);
}
if (pid < 0) {
//创建紫禁城失败
PLOG(ERROR) << "failed to fork for '" << name_ << "'";
pid_ = 0;
return false;
}
...
}
Start开启一个新的子进程,然后执行子进程的二进制,最后传入配置的参数,我们来看配置文件,先选init.zygote64_32.rc作为例子。
//system/core/rootdir/init.zygote64_32.rc
//启动zygote,路径在/system/bin/app_process64 后面都是配置参数
service zygote /system/bin/app_process64 -Xzygote /system/bin --zygote --start-system-server --socket-name=zygote
class main
priority -20
user root
group root readproc
socket zygote stream 660 root system
onrestart write /sys/android_power/request_state wake
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
//zygote_secondary
service zygote_secondary /system/bin/app_process32 -Xzygote /system/bin --zygote --socket-name=zygote_secondary --enable-lazy-preload
class main
priority -20
user root
group root readproc
socket zygote_secondary stream 660 root system
onrestart restart zygote
writepid /dev/cpuset/foreground/tasks
未完待续
以上是关于Android init与zygote启动的主要内容,如果未能解决你的问题,请参考以下文章
Android启动过程——init,Zygote,SystemServer