本文的分析基于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
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
int main(int argc, char** argv) {
if (!strcmp(basename(argv[0]), "ueventd")) {
return ueventd_main(argc, argv);
}
if (!strcmp(basename(argv[0]), "watchdogd")) {
return watchdogd_main(argc, argv);
}
if (REBOOT_BOOTLOADER_ON_PANIC) {
InstallRebootSignalHandlers();
}
add_environment("PATH", _PATH_DEFPATH);
bool is_first_stage = (getenv("INIT_SECOND_STAGE") == nullptr);
//注释1:挂载必须的文件路径
if (is_first_stage) {
……
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));
//system/core/init/init_first_stage.cpp
SetInitAvbVersionInRecovery();
//加载及初始化SELinux
selinux_initialize(true);
……
}
//初始化Kernel Log
InitKernelLogging(argv);
//bionic/libc/bionic/system_properties.cpp
//注释2:初始化属性服务
property_init();
……
//
signal_handler_init();
//导入默认的环境变量
//"/system/etc/prop.default,/odm/default.prop,/vendor/default.prop"
property_load_boot_defaults();
//启动属性服务
start_property_service();
……
const BuiltinFunctionMap function_map;
Action::set_function_map(&function_map);
ActionManager& am = ActionManager::GetInstance();
ServiceManager& sm = ServiceManager::GetInstance();
Parser& parser = Parser::GetInstance();
//make_unique是C++的智能指针,可以自动管理内存
//ServiceParser、ActionParser、ImportParser分别解析service,action,import
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()) {
//若不存在"ro.boot.init_rc"属性,则解析下列文件
parser.ParseConfig("/init.rc"); //注释3,解析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 {
//如果"ro.boot.init_rc"属性存在,则解析属性值
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);
}
……
while (true) {
// By default, sleep until something happens.
int epoll_timeout_ms = -1;
//重置shutting_down标志
if (do_shutdown && !shutting_down) {
do_shutdown = false;
if (HandlePowerctlMessage(shutdown_command)) {
shutting_down = true;
}
}
if (!(waiting_for_prop || sm.IsWaitingForExec())) {
//执行每个Action所带的执行函数
am.ExecuteOneCommand();
}
if (!(waiting_for_prop || sm.IsWaitingForExec())) {
//重启死去的进程
if (!shutting_down) restart_processes();
……
}
}
return 0;
}

init进程做的事较多,但我们只需关注几点:

  1. 注释1处创建和挂载启动所需的文件
  2. 注释2处初始化属性服务,随后调用start_property_service()启动属性服务
  3. 注释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
2
3
on <trigger> [&& <trigger>]*   #触发条件
<command> #操作命令
<command>

例如:

1
2
on charger
class_start charger

只要条件charger成立,便会执行 class_start charger 命令

Services的格式如下:

1
2
3
service <name> <pathname> [<argument>] #<service服务名称><执行文件路径><参数>
<option> #这个服务的一些配置
<option>

例如:

1
2
3
4
5
service 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
2
3
4
5
6
7
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
……

在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
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
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
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

可以看到该文件里有两个service,最大的区别就是对应的可执行文件不一样。可以看到,启动64位的Zygote需要执行/system/bin/app_process64,后面是传入的参数。
那么zygote的service是怎么被解析的呢? 我们回忆一下init.main()。

system/core/init/init.cpp
1
2
3
4
5
6
7
8
9
10
11
12
int main(int argc, char** argv) {
……
ServiceManager& sm = ServiceManager::GetInstance();
Parser& parser = Parser::GetInstance();
//make_unique是C++的智能指针,可以自动管理内存
//ServiceParser、ActionParser、ImportParser分别解析service,action,import
parser.AddSectionParser("service", std::make_unique<ServiceParser>(&sm));
……
parser.ParseConfig("/init.rc");
……
return 0;
}

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
21
bool 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
2
3
bool ServiceParser::ParseLineSection(std::vector<std::string>&& args, int line, std::string* err) {
return service_ ? service_->ParseLine(std::move(args), err) : false;
}

再来看看ParseLine

1
2
3
4
5
6
7
8
bool 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
2
3
4
5
6
7
8
9
10
11
12
13
const Service::OptionParserMap::Map& Service::OptionParserMap::map() const {
constexpr std::size_t kMax = std::numeric_limits<std::size_t>::max();
// clang-format off
static const Map option_parsers = {
……
{"priority", {1,1,&Service::ParsePriority}},
……
{"namespace", {1,2,&Service::ParseNamespace}},
……
};
// clang-format on
return option_parsers;
}

解析完所有数据后,会调用EndSection函数

1
2
3
4
5
void ServiceParser::EndSection() {
if (service_) {
service_manager_->AddService(std::move(service_));
}
}

在EndSection中又调用了ServiceManager的AddService函数。

1
2
3
void 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
2
3
4
on post-fs
……
start servicemanager
……

1.2.3 启动Zygote

system/core/rootdir/init.rc
1
2
3
on nonencrypted
class_start main
class_start late_start

这是一个Action语句,class_start对应的函数是do_class_start, class_start main会启动classname为main的Service

system/core/init/builtins.cpp
1
2
3
4
5
static int do_class_start(const std::vector<std::string>& args) {
ServiceManager::GetInstance().
ForEachServiceInClass(args[1], [] (Service* s) { s->StartIfNotDisabled(); });
return 0;
}

ForEachServiceInClass会找到classname为main的Service,并执行Service的StartIfNotDisabled。

system/core/init/service.cpp
1
2
3
4
5
6
7
8
bool Service::StartIfNotDisabled() {
if (!(flags_ & SVC_DISABLED)) {
return Start();
} else {
flags_ |= SVC_DISABLED_START;
}
return true;
}

接着进入到Start()函数。Start函数较长,这里只截取关键部分分析。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
bool Service::Start() {
flags_ &= (~(SVC_DISABLED|SVC_RESTARTING|SVC_RESET|SVC_RESTART|SVC_DISABLED_START));
//如果Service已经启动,则直接返回
if (flags_ & SVC_RUNNING) {
return false;
}
//对Service判断,设置一些Flag
……
pid_t pid = -1;
if (namespace_flags_) {
pid = clone(nullptr, nullptr, namespace_flags_ | SIGCHLD, nullptr);
} else {
pid = fork();
}
if (pid == 0) {
//fork出子进程后,为子进程设置参数
……
//执行对应Service的对应执行文件
//调用execve函数执行程序
if (!ExpandArgsAndExecve(args_)) {
PLOG(ERROR) << "cannot execve('" << args_[0] << "')";
}
}
……
return true;
}

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进程的启动做了很多工作,主要为以下几点:

  1. 创建和挂载必须的文件路径
  2. 初始化并启动属性服务
  3. 解析并执行init.rc文件的语句

至此,代码流程进入到framework层,关于Zygote进程的启动将在下节讲解。
Android系统启动分析(二)