本文的分析基于Android 8.1源码。
Android系统启动与应用程序的启动流程、四大组件原理、AMS、ClassLoader等息息相关,因此了解Android系统启动流程对深入理解Android有很大的帮助。
本文将分为以下几个小节讲述Android系统的系统流程,分别是:init进程启动、Zygote进程启动、SystemServer进程启动以及Launcher进程启动。
一、init进程启动
都知道当手机关机时不会启动任何一个进程,所以在init进程启动前,Android就为进程的启动做了很多铺垫。具体为:按下电源键加载BootLoader、拉起系统OS、启动Linux内核…但由于本人暂未学到Linux内核,因此前面的暂不做分析(当我没说emmm…)
本节涉及到的文件有:
文件 | 路径 |
init.cpp | system/core/init/init.cpp |
init.rc | system/core/rootdir/init.rc |
init.zygote64_32.rc | system/core/rootdir/init.zygote64_32.rc |
service.cpp | system/core/init/service.cpp |
builtins.cpp | system/core/init/builtins.cpp |
1.1 init.main()
Linux内核启动后,运行的第一个进程是init进程。
system/core/init/init.cpp |
1 | int main(int argc, char** argv) { |
init进程做的事较多,但我们只需关注几点:
- 注释1处创建和挂载启动所需的文件
- 注释2处初始化属性服务,随后调用start_property_service()启动属性服务
- 注释3处解析/init.rc,{/system,/vendor,/odm}/etc/init几个文件
1.2 解析init.rc
init.rc是用Android初始化语言(Android Init Language)编写的文件,在init文件夹中的README对它有描述。感兴趣的可以自行去看。
system/core/init/README.md |
AIL主要包含5种类型的语句:Actions, Commands, Services, Options, Imports.
重点来看看Actions和Services
Actions的格式如下:
1 | on <trigger> [&& <trigger>]* #触发条件 |
例如:
1 | on charger |
只要条件charger成立,便会执行 class_start charger 命令
Services的格式如下:
1 | service <name> <pathname> [<argument>] #<service服务名称><执行文件路径><参数> |
例如:1
2
3
4
5service adbd /system/bin/adbd --root_seclabel=u:r:su:s0
class core
socket adbd stream 660 system system
disabled
seclabel u:r:adbd:s0
这是init.usb.rc的一段代码,用来启动adbd服务
了解了AIL语言后,我们来看看init.rc,代码路径如下:
system/core/rootdir/init.rc |
1 | import /init.environ.rc |
在init.rc开始位置引入了一些rc文件,重点关注Zygote启动相关的文件。/init.${ro.zygote}.rc
这里根据ro.zygote属性值加载对应的rc文件。这个属性值可通过adb shell getprop | grep “zygote”获取。
例如在我的手机上该属性值为: [ro.zygote]: [zygote64_32]
在我手机上启动Zygote会涉及到init.zygote64_32.rc,代码路径如下:
system/core/rootdir/init.zygote64_32.rc |
1 | service zygote /system/bin/app_process64 -Xzygote /system/bin --zygote --start-system-server --socket-name=zygote |
可以看到该文件里有两个service,最大的区别就是对应的可执行文件不一样。可以看到,启动64位的Zygote需要执行/system/bin/app_process64,后面是传入的参数。
那么zygote的service是怎么被解析的呢? 我们回忆一下init.main()。
system/core/init/init.cpp |
1 | int main(int argc, char** argv) { |
AddSectionParser函数将”service”当做键,ServiceParser对象当做值,存到一个map中,执行ParseConfig函数后,会调用ServiceParser的ParseSection和ParseLineSection函数来解析service语句。
1.2.1 解析service
system/core/init/service.cpp |
ServiceParser的实现在 system/core/init/service.cpp中,ParseSection的实现如下:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21bool ServiceParser::ParseSection(std::vector<std::string>&& args, const std::string& filename,int line, std::string* err) {
if (args.size() < 3) {
*err = "services must have a name and a program";
return false;
}
//获取服务名
const std::string& name = args[1];
if (!IsValidName(name)) { //检查service的name是否有效
*err = StringPrintf("invalid service name '%s'", name.c_str());
return false;
}
Service* old_service = service_manager_->FindServiceByName(name);
if (old_service) {
*err = "ignored duplicate definition of service '" + name + "'";
return false;
}
std::vector<std::string> str_args(args.begin() + 2, args.end());
//将service_指针指向当前Service对象
service_ = std::make_unique<Service>(name, str_args);
return true;
}
ParseSection主要检验参数的有效性,并构造一个Service对象。
接下来看看ParseLineSection
1 | bool ServiceParser::ParseLineSection(std::vector<std::string>&& args, int line, std::string* err) { |
再来看看ParseLine1
2
3
4
5
6
7
8bool Service::ParseLine(const std::vector<std::string>& args, std::string* err) {
static const OptionParserMap parser_map;
auto parser = parser_map.FindFunction(args, err); //1
if (!parser) {
return false;
}
return (this->*parser)(args, err); //2
}
ParseLine的作用是为Service的每一个Option指定处理函数。
注释1处FindFunction根据传入的args找到对应的处理函数,并在注释2的return语句中调用。
具体的Options和对应的函数在Service::OptionParserMap::map()中定义
1 | const Service::OptionParserMap::Map& Service::OptionParserMap::map() const { |
解析完所有数据后,会调用EndSection函数1
2
3
4
5void ServiceParser::EndSection() {
if (service_) {
service_manager_->AddService(std::move(service_));
}
}
在EndSection中又调用了ServiceManager的AddService函数。1
2
3void ServiceManager::AddService(std::unique_ptr<Service> service) {
services_.emplace_back(std::move(service));
}
EndSection的主要工作是将解析完成的Service添加到ServiceManager的service_链表中。
1.2.2 启动ServiceManager
ServiceManager用来管理系统中所有的binder service,最主要的作用是注册添加服务和Zygote进程启动。
system/core/rootdir/init.rc |
1 | on post-fs |
1.2.3 启动Zygote
system/core/rootdir/init.rc |
1 | on nonencrypted |
这是一个Action语句,class_start对应的函数是do_class_start, class_start main会启动classname为main的Service
system/core/init/builtins.cpp |
1 | static int do_class_start(const std::vector<std::string>& args) { |
ForEachServiceInClass会找到classname为main的Service,并执行Service的StartIfNotDisabled。
system/core/init/service.cpp |
1 | bool Service::StartIfNotDisabled() { |
接着进入到Start()函数。Start函数较长,这里只截取关键部分分析。
1 | bool Service::Start() { |
Start()函数先通过fork函数创建一个子进程,然后在子进程中调用ExpandArgsAndExecve()->execve()函数启动一个新的程序。fork()+execve()结合可以产生一个新的进程,这里涉及到Linux内核层面,便不再继续深入。
由init.zygote64_32.rc可知,Zygote的执行路径为:/system/bin/app_process64,执行该程序后,不管是32位还是64位系统,都会进入到framework/cmds/app_process/app_main.cpp的main()函数。
由此可知,Zygote进程也不是凭空产生,而是由Init进程fork而来。
1.3 小结
init进程的启动做了很多工作,主要为以下几点:
- 创建和挂载必须的文件路径
- 初始化并启动属性服务
- 解析并执行init.rc文件的语句
至此,代码流程进入到framework层,关于Zygote进程的启动将在下节讲解。
Android系统启动分析(二)